poj 2186 Popular Cows 强连通量分解模板

来源:互联网 发布:网络借贷平台应用 编辑:程序博客网 时间:2024/06/06 00:24

题意:给出m个有序对,(a,b)表示a认识b,此关系具有传递性,找出所有的人都认识的人的个数


思路:强连通分量模板题


题目链接:http://poj.org/problem?id=2186


#include <cstdio>#include <cstring>#include <algorithm>#pragma warning (disable: 4996)//vs中让scanf编译通过using namespace std;const int maxm = 50005;const int maxn = 10005;struct edge1{int u, v, next;}e1[maxm];//按题目顺序输入的前向星struct edge2{int u, v, next;}e2[maxm];//将边反过来的后的前向星int head1[maxn], head2[maxn];//head1对应e1, head2对应e2int cnt1, cnt2;int n, m;bool vis[maxn];int ans[maxn], cnt3;//后序遍历的结果int c[maxn]; //每个点的强连通分量的编号void init(){cnt1 = cnt2 = cnt3 = 0;memset(vis, false, sizeof(vis));memset(head1, -1, sizeof(head1));memset(head2, -1, sizeof(head2));}void addedge(int u, int v){e1[cnt1].u = u, e1[cnt1].v = v, e1[cnt1].next = head1[u], head1[u] = cnt1++;e2[cnt2].u = v, e2[cnt2].v = u, e2[cnt2].next = head2[v], head2[v] = cnt2++;}void dfs1(int u)//进行了后序遍历{vis[u] = true;int v;for (int i = head1[u]; i != -1; i = e1[i].next){v = e1[i].v;if (!vis[v])dfs1(v);}ans[cnt3++] = u;//记录每个点的离开遍历的时间,放在最后也就是后序遍历}void dfs2(int u, int k){vis[u] = true;c[u] = k;int v;for (int i = head2[u]; i != -1; i = e2[i].next){v = e2[i].v;if (!vis[v])dfs2(v, k);}}int scc(){for (int i = 1; i <= n; i++){if (!vis[i])dfs1(i);}memset(vis, false, sizeof(vis));int res = 0, u;for(int i = cnt3 - 1; i >= 0; i--){u = ans[i];if (!vis[u])dfs2(u, ++res);}return res;}int main(){while (~scanf("%d%d", &n, &m)){init();int u, v;for (int i = 0; i < m; i++){scanf("%d%d", &u, &v);addedge(u, v);}int res = scc();int ret = 0;u = 1;for (int i = 1; i <= n; i++){if (c[i] == res){u = i;ret++;}}memset(vis, false, sizeof(vis));dfs2(u, 0);//因为可能存在孤立的点,这样就不是所有的牛都认识最后一个连通分量了for (int i = 1; i <= n; i++){if (!vis[i]){ret = 0;break;}}printf("%d\n", ret);}return 0;}


0 0