题目传送门
题目中文大意:
对于一些点,任意一个点都互相可达,则这些点称为"汇".求每一个"汇"的所有点.
解题思路:
tarjan求强连通分量,缩点,对于所有没有出度的强连通分量的点,就是答案.
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<stack> 4 #include<cstring> 5 #include<vector> 6 #include<algorithm> 7 8 using namespace std; 9 10 int n,m,head[5001],tot,dfn[5001],low[5001],_tot,tt,belong[5001],outd[5001],ans[5001],k; 11 bool _in[5001]; 12 struct kkk { 13 int to,next; 14 }e[25000001]; 15 stack<int> a; 16 17 inline void chushihua() { 18 memset(head,-1,sizeof(head)); 19 memset(belong,0,sizeof(belong)); 20 memset(dfn,0,sizeof(dfn)); 21 memset(low,0,sizeof(low)); 22 memset(outd,0,sizeof(outd)); 23 memset(ans,0,sizeof(ans)); 24 tot = _tot = tt = k = 0; 25 memset(_in,0,sizeof(_in)); 26 } 27 28 inline void add(int x,int y) { 29 e[++tot].next = head[x]; 30 e[tot].to = y; 31 head[x] = tot; 32 } 33 34 inline void tarjan(int x) { 35 int v; 36 a.push(x); 37 dfn[x] = low[x] = ++_tot; 38 _in[x] = true; 39 for(int i = head[x];i != -1; i = e[i].next) { 40 v = e[i].to; 41 if(!dfn[v]) { 42 tarjan(v); 43 low[x] = min(low[x],low[v]); 44 } 45 else 46 if(_in[v]) 47 low[x] = min(low[x],dfn[v]); 48 } 49 if(dfn[x] == low[x]) { 50 ++tt; 51 do { 52 v = a.top(); 53 a.pop(); 54 _in[v] = false; 55 belong[v] = tt; 56 } 57 while(v != x); 58 } 59 } 60 61 inline void _ans(int x) { 62 for(int i = 1;i <= n; i++) 63 if(belong[i] == x) 64 ans[++k] = i; 65 } 66 67 inline void _print() { 68 sort(ans+1,ans+k+1); 69 for(int i = 1;i <= k; i++) 70 printf("%d ",ans[i]); 71 printf(" "); 72 } 73 74 int main() 75 { 76 while(true) { 77 chushihua(); 78 scanf("%d",&n); 79 if(n == 0) return 0; 80 scanf("%d",&m); 81 for(int i = 1;i <= m; i++) { 82 int x,y; 83 scanf("%d%d",&x,&y); 84 add(x,y); 85 } 86 for(int i = 1;i <= n; i++) 87 if(!dfn[i]) 88 tarjan(i); 89 for(int i = 1;i <= n; i++) 90 for(int j = head[i];j != -1; j = e[j].next) 91 if(belong[i] != belong[e[j].to]) 92 outd[belong[i]]++; 93 for(int i = 1;i <= tt; i++) 94 if(outd[i] == 0) 95 _ans(i); 96 _print(); 97 } 98 return 0; 99 }