您的位置:首页 > 运维架构

POJ 2762 Going from u to v or from v to u?【强连通+toposort】

2012-10-03 17:39 513 查看
题意: 给出一个有n 个节点的和m 条单向边,问图中是否任意两点都是连通的,这里连通的定义为:u,v连通,则存在一条从u到v的边或存在一条从v到u的边。

分析:因为在一个强连通分量内部的点是两两可达的,所以可以先对所有的强连通分量缩点,即把强连通分量内部的点看成是一个点。如果两点不可达那么在拓

扑排序时,该两点谁也不是谁的前驱和后继,所以在拓扑排序时只要同时出现至少两个入度为0的点,那么这些点一定互不可达,所以只要判断拓扑的方式

是否唯一即可。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define maxn 1005
struct node
{
int to,next;
}e[100000],edge[1000000];
int tot;
int tt;
int head[maxn];
int toph[maxn];
void add(int s,int t)
{
e[tot].to=t;
e[tot].next=head[s];
head[s]=tot++;
}
void addedge(int s,int t)
{
edge[tt].to=t;
edge[tt].next=toph[s];
toph[s]=tt++;
}
int ti,sn,top,n;
int dfn[maxn];
int low[maxn];
int ins[maxn];
int sta[maxn];
int col[maxn];
int ind[maxn];
void tarjan(int u)
{
dfn[u]=low[u]=++ti;
ins[u]=1;
sta[++top]=u;
int i,k;
for(i=head[u];i;i=e[i].next)
{
k=e[i].to;
if(dfn[k]==0)
{
tarjan(k);
low[u]=min(low[u],low[k]);
}
else if(ins[k])
low[u]=min(low[u],dfn[k]);
}
if(dfn[u]==low[u])
{
sn++;
do
{
k=sta[top--];
ins[k]=0;
col[k]=sn;
}while(k!=u);
}
}
int q[maxn];
int toposort()
{
int front,rear;
front=rear=0;
int i,k;
for(i=1;i<=sn;i++)
if(ind[i]==0)
q[rear++]=i;
if(rear!=1)
return 0;
int num=0;
while(front<rear)
{
int x=q[front++];
int tt=0;
num++;
for(i=toph[x];i;i=edge[i].next)
{
k=edge[i].to;
ind[k]--;
if(ind[k]==0)
{
q[rear++]=k;
tt++;
}
}
if(tt>1)
return 0;
}
if(num==sn)
return 1;
return 0;
}
int main()
{
int t,m,i,j,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
clr(head);
tot=1;
int a,b;
while(m--)
{
scanf("%d%d",&a,&b);
add(a,b);
}
clr(dfn);
sn=top=ti=0;
for(i=1;i<=n;i++)
if(dfn[i]==0)
tarjan(i);
clr(toph);
tt=1;
clr(ind);
for(i=1;i<=n;i++)
for(j=head[i];j;j=e[j].next)
{
k=e[j].to;
if(col[i]!=col[k])
{
ind[col[k]]++;
addedge(col[i],col[k]);
}
}
printf("%s\n",toposort()?"Yes":"No");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: