您的位置:首页 > 编程语言 > Go语言

pku 2762 Going from u to v or from v to u?

2011-08-01 17:12 351 查看
强联通+拓扑排序判断~~

题目大意:给定一个有向图,问该图是不是半连通图.

所谓半连通图即是指 在连通图中任意给出两个点a,b,要保证至少存在一条从a到b,或者从b到a的边。

解题思路:先用强联通进行缩点,之后再重新建图,再用拓扑排序进行判断:当某一时刻存在两个或两个以上入度为0的点则输出No,否则输出Yes!

为了学习双联通不得不学习了tarjan,先用tarjan把这个题给A了。之后不太过瘾,又用Kosaraju给A了下,结果发现Kosaraju要比tarjan更快。。很神奇。。

可能是因为我写的tarjan太丑陋了!! 或者是我写的Kosaraju更风骚一点。。 ^_^。。 不过我感觉还是后者比较容易理解一点,我写的也比较清晰!!

分别贴下两种方法的代码:

tarjan:

View Code

# include<stdio.h>
# include<string.h>
# define N 1005
# define M 6005
struct node{
int from,to,next;
}edge1[M],edge2[M],edge[M];
int head1
,visit1
,visit2
,head2
,T
,Belong
,head
,degree
;
int tol1,tol2,tol,Tcnt,Bcnt,n,m;
void add1(int a,int b)
{
edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
}
void add(int a,int b)
{
edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
}
void dfs1(int i)
{
int j,u;
visit1[i]=1;
for(j=head1[i];j!=-1;j=edge1[j].next)
{
u=edge1[j].to;
if(!visit1[u]) dfs1(u);
}
T[Tcnt++]=i;
}
void dfs2(int i)
{
int j,u;
visit2[i]=1;
Belong[i]=Bcnt;
for(j=head2[i];j!=-1;j=edge2[j].next)
{
u=edge2[j].to;
if(!visit2[u]) dfs2(u);
}
}
int main()
{
int i,j,ncase,count,index,a,b;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d%d",&n,&m);
tol1=tol2=0;
Bcnt=Tcnt=0;
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(visit1,0,sizeof(visit1));
memset(visit2,0,sizeof(visit2));
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add1(a,b);
}
for(i=1;i<=n;i++)
if(!visit1[i]) dfs1(i);
for(i=Tcnt-1;i>=0;i--)
{
if(!visit2[T[i]])
{
dfs2(T[i]);
Bcnt++;
}
}
memset(head,-1,sizeof(head));
memset(degree,0,sizeof(degree));
tol=0;
for(i=0;i<tol1;i++)
{
a=edge1[i].from;
b=edge1[i].to;
if(Belong[a]!=Belong[b])
{
add(Belong[a],Belong[b]);
degree[Belong[b]]++;
}
}
count=0;
for(i=0;i<Bcnt;i++)
{
if(degree[i]==0)
{
count++;
index=i;
}
}
if(count>1) {printf("No\n");continue;}
while(1)
{
count=0;
for(j=head[index];j!=-1;j=edge[j].next)
{
i=edge[j].to;
degree[i]--;
if(degree[i]==0)
{
count++;
index=i;
}
}
if(count>1) {printf("No\n");break;}
else if(count==0) {printf("Yes\n");break;}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: