首页 > 代码库 > POJ 2186.Popular Cows 解题报告

POJ 2186.Popular Cows 解题报告

强连通缩点,统计入度为1的缩点后的点的个数

个数1的话输出这个强连通分量的点的数量

否则输出0;

code

/*       Kosaraju算法,无向图的强连通分量,时间复杂度O(n+m)       思路:       按照图G的深度遍历序列,在G的反图上进行深搜       能够搜到的点集就是一个强联通分量*/#include <iostream>#include <cstring>using namespace std;const int INF = 10009;//链接表,偶数边为原图,奇数边为反图struct node {	int v, ne;} edge[100009];/*   scc是强连通子图的个数   dfn为深度遍历序列(逆序即反图的拓扑排序)   vis为访问标记,sum记录每个强连通分量的节点数*/int head[INF], dfn[INF], vis[INF], sum[INF], n, m, scc, cnt = 1, tol;void adde (int u, int v) {	edge[++cnt].v = v;	edge[cnt].ne = head[u];	head[u] = cnt;}void dfs (int k) {	vis[k] = 1;	for (int i = head[k]; i != 0; i = edge[i].ne)		if ( (i & 1) == 0 && !vis[edge[i].v])			dfs (edge[i].v);	dfn[++tol] = k;}void ndfs (int k) {	vis[k] = scc, sum[scc]++;	for (int i = head[k]; i != 0; i = edge[i].ne)		if ( (i & 1)  && !vis[edge[i].v])			ndfs (edge[i].v);}void Kosaraju() {	for (int i = 1; i <= n; i++)		if (!vis[i])     dfs (i);	memset (vis, 0, sizeof vis);	for (int i = n; i > 0; i--)		if (!vis[dfn[i]])  scc++, ndfs (dfn[i]);}int make() {	int deg[INF] = {0};	//由反图统计每个强联通点的有无出度	for (int i = 3; i <= cnt; i += 2) {		if (vis[edge[i].v] == vis[edge[i ^ 1].v]) continue;		deg[vis[edge[i].v]]++;	}	int j, t = 0;	for (int i = 1; i <= scc; i++)		if (deg[i] == 0) j = i, t++;	if (t == 1) return sum[j];	return 0;}int main() {	int x, y;	cin >> n >> m;	for (int i = 1; i <= m; i++) {		cin >> x >> y;		adde (x, y), adde (y, x);	}	Kosaraju();	cout << make();	return 0;}

  

POJ 2186.Popular Cows 解题报告