POJ 2186 Popular Cows

POJ_2186

       这个题目其实就是求完强连通分量之后,判断一下出度为0的强连通分量是否唯一,如果唯一输出该强连通分量的点数,否则输出0

由于之前求强连通分量的时候是把同一个强连通分量里的数放到一个数组里,然后枚举各个数组之间各元素是否有边来判断各个强连通分量是否连通,由于这样效率比较低,这次超时了。

后来看了别人的代码后发现,其实可以找到强连通分量之后,把其中的每个元素都染成一个颜色(开一个数组paint[]来记录染色情况,颜色用num表示,初始化为0),最后枚举所有边,如果一条边(u,v)两个端点的颜色不一样,那么就让outdgr[paint[u]]++。当然,这样最后outdgr中存的并不是强连通分量的出度,但如果outdgr的值为0,那么该强连通分量的值也一定为0,因此用outdgr来判断强连通分量的出度是否为0是完全可以的。

另外,写代码的时候又犯了一些错误:①tarjan中把low[u]dfn[u]的值初始化成了u;②最后让同一强连通分量里的点出栈时,没有先令s[top]=-1再进行出栈操作。以后一定要注意!

#include<stdio.h>
#include
<string.h>
int ins[10010],top,dfn[10010],time,low[10010],s[10010];
int paint[10010],member[10010],num,outdgr[10010];
int first[10010],next[50010],u[50010],v[50010];
void tarjan(int a)
{
int e,b,temp;
dfn[a]
=low[a]=++time;
s[top
++]=a;
ins[a]
=1;
for(e=first[a];e!=-1;e=next[e])
{
b
=v[e];
if(!dfn[b])
{
tarjan(b);
if(low[b]<low[a])
low[a]
=low[b];
}
else if(ins[b]&&dfn[b]<low[a])
low[a]
=dfn[b];
}
if(dfn[a]==low[a])
{
member[num]
=0;
s[top]
=-1;
while(s[top]!=a)
{
temp
=s[--top];
ins[temp]
=0;
paint[temp]
=num;
member[num]
++;
}
num
++;
}
}
int main()
{
int i,j,k,e,a,N,M,count;
while(scanf("%d%d",&N,&M)==2)
{
for(i=1;i<=N;i++)
first[i]
=-1;
for(e=0;e<M;e++)
{
scanf(
"%d%d",&u[e],&v[e]);
next[e]
=first[u[e]];
first[u[e]]
=e;
}
memset(dfn,
0,sizeof(dfn));
memset(ins,
0,sizeof(ins));
time
=num=top=0;
for(a=1;a<=N;a++)
if(!dfn[a])
tarjan(a);
memset(outdgr,
0,sizeof(outdgr));
for(i=0;i<M;i++)
if(paint[u[i]]!=paint[v[i]])
outdgr[paint[u[i]]]
++;
count
=0;
for(i=0;i<num;i++)
if(outdgr[i]==0)
{
count
++;
k
=i;
}
if(count>1)
{
printf(
"0\n");
continue;
}
printf(
"%d\n",member[k]);
}
return 0;
}

  

你可能感兴趣的:(poj)