poj 2186 有向图强连通分量

奶牛互相之间有爱慕关系,找到被其它奶牛都喜欢的奶牛的数目

用tarjan缩点,然后判断有向图中出度为0的联通分量的个数,如果为1就输出联通分量中的点的数目,否则输出0.

算法源自kb模板

  1 #include<cstdio>

  2 #include<iostream>

  3 #include<cstring>

  4 const int MAXN=20010;//点数

  5 const int MAXM=50010;//边数

  6 struct Edge

  7 {

  8     int to,next;

  9 }edge[MAXM];

 10 int head[MAXN],tot;

 11 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc

 12 int Index,top;

 13 int scc;//强连通分量的个数

 14 bool Instack[MAXN];

 15 int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc

 16 //num数组不一定需要,结合实际情况

 17 int out[MAXN],tmp,Num,ans;

 18 void addedge(int u,int v)

 19 {

 20     edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;

 21 }

 22 void Tarjan(int u)

 23 {

 24     int v;

 25     Low[u]=DFN[u]=++Index;

 26     Stack[top++]=u;

 27     Instack[u]=true;

 28     for(int i=head[u];i != -1;i=edge[i].next)

 29     {

 30         v=edge[i].to;

 31         if(!DFN[v])

 32         {

 33             Tarjan(v);

 34             if(Low[u] > Low[v])Low[u]=Low[v];

 35         }

 36         else if(Instack[v] && Low[u] > DFN[v])

 37         Low[u]=DFN[v];

 38     }

 39     if(Low[u]==DFN[u])

 40     {

 41         scc++;

 42         do

 43         {

 44             v=Stack[--top];

 45             Instack[v]=false;

 46             Belong[v]=scc;

 47             num[scc]++;

 48         }

 49         while(v != u);

 50     }

 51 }

 52 void solve(int N)

 53 {

 54     memset(out,0,sizeof(out));

 55     memset(Belong,0,sizeof(Belong));

 56     memset(DFN,0,sizeof(DFN));

 57     memset(Instack,false,sizeof(Instack));

 58     memset(num,0,sizeof(num));

 59     Index=scc=top=0;

 60     for(int i=1;i <= N;i++)

 61         if(!DFN[i])

 62             Tarjan(i);

 63 }

 64 void init()

 65 {

 66     tot=0;

 67     memset(head,-1,sizeof(head));

 68 }

 69 int main()

 70 {

 71     int n,m;

 72     int i,j,v;

 73     //freopen("1.in","r",stdin);

 74     while(scanf("%d%d",&n,&m)!=EOF)

 75     {

 76         init();

 77         int q,p;

 78         for(i=1;i<=m;i++)

 79         {

 80             scanf("%d%d",&p,&q);

 81             addedge(p,q);

 82         }

 83         solve(n);

 84         for(i=1;i<=n;i++)

 85         {

 86             for(v=head[i];v!=-1;v=edge[v].next)

 87             {

 88                 if(Belong[i]!=Belong[edge[v].to])

 89                 {

 90                     out[Belong[i]]++;

 91                 }

 92             }

 93         }

 94         ans=0,Num=0;

 95         for(i=1;i<=scc;i++)

 96         {

 97             if(!out[i])

 98             {

 99                 Num++;

100                 tmp = i;

101             }

102         }

103         if(Num==1)

104         {

105             for(i=1;i<=n;i++)

106             {

107                 if(Belong[i]==tmp)

108                     ans++;

109             }

110             printf("%d\n",ans);

111         }

112         else

113         {

114             printf("0\n");

115         }

116     }

117     return 0;

118 }

 

你可能感兴趣的:(poj)