【强连通分量】10204 - 谁是孽角子
Time Limit: 1000MS
Memory Limit: 2048KB
本题由南山卢致远原创!在此感谢!
NSOI 选孽角子了,负责扫地的孽角子,由于大家风度太好,所有都不愿意去争取,经过叶老师的再三思考,决定来一次投票推荐,参加投票的有N个人,将他们按1 — N编号。自己是憋憋推荐自己的、注意,一个人可以投多个人。Nsoi之间的信任存在传递性,如果,A支持B,那么A也会支持B支持的人。如果某个人接获得 所有人的推荐,那么他就有可能是孽角子,这个任务交给了致标,致标抓于马下,所以向你求助,任务统计所有可能是孽角子的人。
输入 :
Glover.in
第一行 N,M 有N个人参加了投票,共投M票。 N<=10000 , M<=40000
接下来 M 行,每行两个正整数 a , b ; 表示 a 推荐 b; a <= N && b
<= N ;
输出:
Glover.out
第一行 :ANS_N 表示有ANS_N个人有机会成为孽角子。
接下来 ANS_N 行, 每行一个数 ,表示有机会成为孽角子人的编号。
样例 :
Glover.in
7 10
1 2
2 4
4 3
2 3
3 6
3 5
5 6
6 7
7 5
1 6
Glover.out
3
5
6
7
1 # include<cstdio> 2 # include<cstring> 3 # include<stack> 4 # include<algorithm> 5 # include<iostream> 6 using namespace std; 7 const int N=30000+10; 8 const int M=60000+10; 9 stack<int>S; 10 int n,m,ecnt,scc_cnt,dfs_clock,tot,out_degree,cur; 11 int fist[N],next[M],v[M],pre[N],low[N],scc_no[N],size[N],out[N]; 12 void built(int a,int b){ 13 ++ecnt; 14 v[ecnt]=b; 15 next[ecnt]=fist[a]; 16 fist[a]=ecnt; 17 } 18 int check(int a,int b){ 19 for(int e=fist[a];e!=-1;e=next[e]) 20 if(v[e]==b)return 0; 21 return 1; 22 } 23 void init(){ 24 int a,b; 25 memset(fist,-1,sizeof(fist)); 26 scanf("%d%d",&n,&m); 27 for(int i=1;i<=m;i++){ 28 scanf("%d%d",&a,&b); 29 if(check(a,b)) 30 built(a,b); 31 } 32 } 33 int dfs(int u){ 34 int lowu=pre[u]=++dfs_clock; 35 S.push(u); 36 for(int e=fist[u];e!=-1;e=next[e]) 37 if(!pre[v[e]]) 38 lowu=min(lowu,dfs(v[e])); 39 else if(!scc_no[v[e]]) 40 lowu=min(lowu,pre[v[e]]); 41 low[u]=lowu; 42 if(low[u]==pre[u]){ 43 scc_cnt++; 44 for(;;){ 45 int x=S.top();S.pop(); 46 scc_no[x]=scc_cnt; 47 if(x==u)break; 48 } 49 } 50 return low[u]; 51 } 52 void find_scc(){ 53 memset(pre,0,sizeof(pre)); 54 memset(low,0,sizeof(low)); 55 for(int i=1;i<=n;i++) 56 if(!pre[i])dfs(i); 57 } 58 void work(){ 59 for(int i=1;i<=n;i++)for(int e=fist[i];e!=-1;e=next[e]) 60 if(scc_no[i]!=scc_no[v[e]])out[scc_no[i]]++; 61 for(int i=1;i<=scc_cnt;i++)if(out[i]==0){out_degree=i;cur++;} 62 if(cur!=1){printf("0");return;} 63 for(int i=1;i<=n;i++)if(scc_no[i]==out_degree)tot++; 64 printf("%d\n",tot); 65 for(int i=1;i<=n;i++)if(scc_no[i]==out_degree)printf("%d\n",i); 66 } 67 int main(){ 68 init(); 69 find_scc(); 70 work(); 71 return 0; 72 }
时间: 2024-10-12 14:43:13