poj 1236 Network of Schools 强连通分量

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

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


对于第一问就很简单了,只需要求出缩点后入度为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;
}


你可能感兴趣的:(poj 1236 Network of Schools 强连通分量)