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

POJ 2762 Going from u to v or from v to u?(强连通分量)

2012-10-08 23:19 453 查看
题目链接:http://poj.org/problem?id=2762

题意:给定一个有向图。问这个图是否满足下面的性质:对于图中任意两个顶点u和v,存在u到v的路径或者v到u的路径.

思路:步骤如下:

(1)求强连通分量;

(2)缩点:将原图换成新图;

(3)在新图中拓扑排序,若每次只有一个入度为0的点,则满足题意。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

struct Node
{
int v,next;
};

Node edges[6005];
int head[1005],e;
int n,m,C;
int st[1005],top,dfn[1005],low[1005],ID,num,visit[1005];
int p[1005];

void Add(int u,int v)
{
edges[e].v=v;
edges[e].next=head[u];
head[u]=e++;
}

void DFS(int u)
{
ID++;
dfn[u]=low[u]=ID;st[top++]=u;visit[u]=1;
int i,v;
for(i=head[u];i!=-1;i=edges[i].next)
{
v=edges[i].v;
if(!dfn[v])
{
DFS(v);
low[u]=min(low[u],low[v]);
}
else if(visit[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]>=dfn[u])
{
num++;
do
{
v=st[top-1];
visit[v]=0;
p[v]=num;
top--;
}while(v!=u);

}
}

int g[1005][1005];
int deg[1005];

int OK()
{
int i,j,u,v,x;
memset(g,0,sizeof(g));
memset(deg,0,sizeof(deg));
for(u=1;u<=n;u++)
{
for(i=head[u];i!=-1;i=edges[i].next)
{
v=edges[i].v;
if(p[u]!=p[v]&&!g[p[u]][p[v]])
{
g[p[u]][p[v]]=1;
deg[p[v]]++;
}
}
}
for(i=1;i<num;i++)
{
x=0;
for(j=1;j<=num;j++) if(deg[j]==0) x++,u=j;
if(x>1) return 0;
for(v=1;v<=num;v++) if(g[u][v]) deg[v]--;
deg[u]=-1;
}
return 1;
}

int main()
{
for(scanf("%d",&C);C--;)
{
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
e=0;
int u,v,i;
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
Add(u,v);
}
top=0;ID=0;num=0;
memset(dfn,0,sizeof(dfn));
memset(visit,0,sizeof(visit));
for(i=1;i<=n;i++) if(!dfn[i]) DFS(i);
if(OK()) puts("Yes");
else puts("No");
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: