题意:
有一群牛, a会认为b很帅, 且这种认为是传递的. 问有多少头牛被其他所有牛认为很帅~
思路:
关键就是分析出缩点之后的有向树只能有一个叶子节点(出度为0).
做法就是Tarjan之后缩点统计出度.
#include <cstdio> #include <cstring> #include <stack> #include <algorithm> using namespace std; const int MAXN = 10005; const int MAXE = 50005; struct pool { int v,pre; }p[MAXE]; int num,head[MAXN]; int dfn[MAXN],low[MAXN],id[MAXN],dag[MAXN]; bool vis[MAXN]; int size,Index,n,m; stack<int> s; void add(int u, int v) { p[++num].v = v; p[num].pre = head[u]; head[u] = num; } void Tarjan(int u) { low[u] = dfn[u] = ++Index; vis[u] = true; s.push(u); for(int tmp = head[u],k;k = p[tmp].v,tmp;tmp = p[tmp].pre) { if(!dfn[k]) { Tarjan(k); low[u] = min(low[u],low[k]); } else if(vis[k]) low[u] = min(low[u],low[k]); } if(dfn[u]==low[u]) { size++; int k; do { k = s.top();s.pop(); vis[k] = false; id[k] = size; }while(k!=u); } } void shrink() { for(int i=1;i<=n;i++) for(int tmp = head[i],k;k = p[tmp].v,tmp;tmp = p[tmp].pre) if(id[i]!=id[k]) dag[id[i]]++;//缩点 } int main() { scanf("%d %d",&n,&m); for(int i=0,u,v;i<m;i++) { scanf("%d %d",&u,&v); add(u, v); } for(int i=1;i<=n;i++) { if(!dfn[i]) Tarjan(i); } shrink(); int ans = 0,tmp; for(int i=1;i<=n;i++) { if(!dag[id[i]]) { if(!ans) tmp = id[i]; else if(tmp!=id[i]) { ans = 0; break; } ans++; } } printf("%d ",ans); }