poj 1236 Network of Schools 强连通分量

来源:互联网 发布:手机数据怎么连接电脑 编辑:程序博客网 时间:2024/04/27 19:06

题意:给你一个有向图,第一问:增加一个点至少需要加多少边使得该点能到达其他所有点。

第二问:至少需要加多少边使得整个图变成一个强连通分量。


对于第一问就很简单了,只需要求出缩点后入度为0的点的个数,对于第二问的话,需要求出缩点后入度为0的个数和出度为0的个数,较大值为答案。

比如0出度大于0入度,这样把所有0出度的连到不为该节点祖先的其他子树的0入度节点上,画个图应该很明白。


第一道强连通,很多细节刚开始出错了,现在印象很深刻了~


#include <stdio.h>#include <string.h>const int maxn = 111;const int maxm = 111*111;struct EDGE{int to, vis, next;}edge[maxm];int head[maxn], belo[maxn], low[maxn], dfn[maxn], st[maxn], rudu[maxn], chudu[maxn], ins[maxn];int E, time, top, type, stot;void newedge(int u, int to) {edge[E].to = to;edge[E].vis = 0;edge[E].next = head[u];head[u] = E++;}void init() {memset(head, -1, sizeof(head));memset(dfn, 0, sizeof(dfn));memset(belo, 0, sizeof(belo));memset(rudu, 0, sizeof(rudu));memset(chudu, 0, sizeof(chudu));memset(ins, 0, sizeof(ins));E = time = top = type = 0;}int min(int a, int b) {return a > b ? b : a;}int max(int a, int b) {return a > b ? a : b;}void dfs(int u) {dfn[u] = low[u] = ++time;st[++top] = u;ins[u] = 1;for(int i = head[u];i != -1;i = edge[i].next) {if(edge[i].vis)continue;edge[i].vis = 1;int to = edge[i].to;if(!dfn[to]) {dfs(to);low[u] = min(low[u], low[to]);}else if(ins[to]) {low[u] = min(low[u], low[to]);}}if(low[u] == dfn[u]) {type++;int to;do {to = st[top--];belo[to] = type;ins[to] = 0;} while(to != u);}}void DFS(int u) {for(int i = head[u];i != -1;i = edge[i].next) {if(!edge[i].vis)continue;edge[i].vis = 0;int to = edge[i].to;DFS(to);if(belo[to] != belo[u]) {chudu[belo[u]]++;rudu[belo[to]]++;}}}int main() {init();int i, n, to, u;scanf("%d", &n);for(i = 1;i <= n; i++) {while(scanf("%d", &to) && to) {newedge(i, to);}}for(i = 1;i <= n ;i++) if(!dfn[i])dfs(i);if(type == 1) {printf("1\n0\n");return 0;}for(i = 1;i <= n; i++)DFS(i);int ans1 = 0, ans2 = 0;for(i = 1;i <= type; i++) {if(rudu[i] == 0)ans1++;if(chudu[i] == 0)ans2++;}ans2 = max(ans1, ans2);printf("%d\n%d\n", ans1, ans2);return 0;}


原创粉丝点击