P2341 [HAOI2006]受欢迎的牛
题目大意
题面已经说的够明白了
我只是为了多一个标题,走走过场,好看QwQ
思路
题目明确给出的条件足够裸。既然牛的爱慕关系可以传递,那么自然地就想到了连通分量喽。只要是在同一个连通分量内的牛,它他们对整个局面造成的影响是一致的。那么就可以通过Tarjan算法进行缩点。所点后统计每个强连通分量的出度。如果只有一个出度为零的强连通分量(注意是强连通分量),那么这个点就是受欢迎的牛。如果存在两个以上的话,就证明它俩个都没有互相爱慕,那么肯定就不存在受欢迎的牛,所以直接输出0
吐槽一下
woc,Tarjan写错了都能刚出85分来,学到了学到了,我之前交的时候++Index写成了Index++。。。遛了遛了
代码
#include <iostream> #include <cstring> #include <cstdio> #include <stack> const int maxnode = 1e4+3; const int maxedge = 5e4+3; using namespace std; stack<int> S; int n, m, first[maxnode], next[maxedge], u[maxedge], v[maxedge], num[maxnode]; int low[maxnode], dfn[maxnode], Index, cnt, in[maxnode], Indgr[maxnode]; bool vis[maxnode]; inline int readInt() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while (c <= '9' && c >= '0') { x = x*10 + c-'0'; c = getchar(); } return x * f; } inline void addedge(int f, int i) { next[i] = first[f]; first[f] = i; } inline void Tarjan(int x) { low[x] = dfn[x] = ++Index; vis[x] = 1; S.push(x); int k = first[x]; while (k != -1) { if(!dfn[v[k]]) { Tarjan(v[k]); low[x] = min(low[x], low[v[k]]); } else if(vis[v[k]]) { low[x] = min(low[x], dfn[v[k]]); } k = next[k]; } if(dfn[x] == low[x]) { cnt++; while (!S.empty()) { int temp = S.top(); S.pop(); vis[temp] = 0; in[temp] = cnt; num[cnt]++; if(temp == x) break; } } } int main() { n = readInt(), m = readInt(); memset(first, -1, sizeof(first)); for(int i=1; i<=m; i++) { u[i] = readInt(); v[i] = readInt(); addedge(u[i], i); } for(int i=1; i<=n; i++) { if(!dfn[i]) Tarjan(i); } for(int i=1; i<=n; i++) { int k = first[i]; while (k != -1) { if(in[v[k]] != in[u[k]]) Indgr[in[u[k]]]++; k = next[k]; } } int mark = 0; for(int i=1; i<=cnt; i++) { if(Indgr[i] == 0) { if(mark) { printf("0 "); return 0; } mark = i; } } printf("%d", num[mark]); }