【强连通分量】10204 - 谁是孽角子

【强连通分量】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 }

 

你可能感兴趣的:(【强连通分量】10204 - 谁是孽角子)