现在的位置: 首页 > 综合 > 正文

poj – 2186- 强连通 – 最受欢迎的牛的个数

2014年01月02日 ⁄ 综合 ⁄ 共 1612字 ⁄ 字号 评论关闭

刘汝佳的书上有详细的介绍, 并且这个代码几乎和书上的是一样的

强连通就是“相互到达的关系”,每一个集合称为有向图的一个强连通分量。如果把每一个集合看成一个点,那么所有SCC构成一个SCC图,这个SCC图不会存在有向环,因此是一个DAG------------------"缩点"

此题用了个定理 :有向无环图(DAG)中,从任意一个点出发,必定可以到达某一个出度为0的点。

这个不用证明,直观想一下就行了。  因为无环,所以从一个点出发,必定会到达终点,终点的出度即是0

求强连通的目的也就是将原图改造成一个DAG,因为将属于同一强连通分支的看作一点后,这个新图就是一个DAG

我们统计DAG中出度为0的个数,如果大于1,说明出度为0的“点”不止一个,也就没有题目中要求的能够被其他所有点到达的点。(A single integer that is the number of cows who are considered popular
by every other cow.

如果出度为0的“点”(强连通分支),只有一个,那么该强连通分支中所有的点即可被剩下的点到达。该分支点的个数即是答案。

代码:

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <cstring>
#define maxn 10001

using namespace std;

vector<int> G[maxn];
int n, m, scc_num[maxn];
bool out[maxn];
int pre[maxn], sccno[maxn], dfs_clock, scc_cnt;
stack<int> S;

int dfs( int u )
{
	int lowu = pre[u] = ++dfs_clock;
	S.push(u);
	for( int i = 0; i < G[u].size(); i++ )
	{
		int v = G[u][i];
		if( !pre[v] )
		{
			int lowv = dfs(v);
			lowu = min( lowu, lowv );
		} else if( !sccno[v] ) {
			lowu = min( lowu,pre[v] );
		}
	}
	if( lowu == pre[u] ) {
		scc_cnt++;
		while( 1 )
		{
			int x = S.top();	S.pop();
			sccno[x] = scc_cnt;
			scc_num[scc_cnt]++;
			if(x == u) break;
		}
	}
	return lowu;
}

int find_scc()
{
	dfs_clock = scc_cnt = 0;
	memset(sccno,0,sizeof(sccno));
	memset(pre,0,sizeof(pre));
	memset(scc_num,0,sizeof(scc_num));
	memset(out,0,sizeof(out));
	for( int i = 0; i < n; i++ )
		if( !pre[i] ) dfs(i);

	for( int u = 0; u < n; u++ )
	{
		for( int i = 0; i < G[u].size(); i++ )
		{
			int v = G[u][i];
			if( sccno[u] != sccno[v] )
				out[ sccno[u] ] = 1;
		}
	}

	bool flag = 0;	int t = -1;

	for( int i = 1; i <= scc_cnt; i++ )
	if( !flag && !out[i] ) { flag = 1; t = i; }
	else if( flag && !out[i] ) return 0;

	if( flag ) return scc_num[t];

	return 0;
}

int main() {
	while( ~scanf( "%d%d", &n, &m ) )
	{
		for( int i = 0; i < n; i++ ) G[i].clear();

		for( int i = 0; i < m; i++ )
		{
			int u,v;
			scanf( "%d%d", &u, &v );
			G[--u].push_back(--v);
		}

		printf( "%d\n", find_scc() );
	}
	return 0;
}

抱歉!评论已关闭.