链接:https://vjudge.net/problem/POJ-2186
题意:
有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1,但是如果2也欢迎3那么1也欢迎3.
给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量。
思路:
强连通分量, 缩点。
先求出强连通分量,在根据缩点建立新图。
缩点:即在原图上,将一个强连通子图给看成一个点来处理,本题被所有牛都欢迎的牛,
就是在一个缩点后的图中,出度为0的点,点中的所有牛都是满足条件的牛。
如果出度为0的点大于1,则没有一个牛满足条件。
代码:
#include <iostream> #include <memory.h> #include <cstdio> #include <map> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <algorithm> using namespace std; typedef long long LL; const int MAXN = 1e4+10; vector<int> G[MAXN]; stack<int> St; int Dfn[MAXN], Low[MAXN]; int Fa[MAXN], Vis[MAXN]; int Dis[MAXN]; int n, m; int sum, times; int cnt; void Tarjan(int x) { St.push(x); Vis[x] = 1; Dfn[x] = Low[x] = ++times; for (int i = 0;i < G[x].size();i++) { int node = G[x][i]; if (Dfn[node] == 0) { Tarjan(node); Low[x] = min(Low[x], Low[node]); } else if (Vis[node] == 1) { Low[x] = min(Low[x], Dfn[node]); } } if (Dfn[x] == Low[x]) { cnt++; while (St.top() != x) { Fa[St.top()] = cnt; Vis[St.top()] = 0; St.pop(); } Fa[St.top()] = cnt; Vis[St.top()] = 0; St.pop(); } } void Init() { for (int i = 1;i <= n;i++) G[i].clear(), Fa[i] = i; while (St.size()) St.pop(); memset(Dfn, 0, sizeof(Dfn)); memset(Low, 0, sizeof(Low)); memset(Vis, 0, sizeof(Vis)); memset(Dis, 0, sizeof(Dis)); cnt = times = 0; } int main() { while (cin >> n >> m) { int l, r; for (int i = 1;i <= m;i++) { cin >> l >> r; G[l].push_back(r); } for (int i = 1;i <= n;i++) if (Dfn[i] == 0) Tarjan(i); for (int i = 1;i <= n;i++) { for (int j = 0;j < G[i].size();j++) { int node = G[i][j]; if (Fa[i] != Fa[node]) Dis[Fa[i]]++; } } int ans = 0, u; for (int i = 1;i <= cnt;i++) if (Dis[i] == 0) ans++, u = i; if (ans == 1) { int res = 0; for (int i = 1;i <= n;i++) if (Fa[i] == u) res++; cout << res << endl; } else cout << 0 << endl; } return 0; }