题目大意就是说,判断有向图是否是强连通图,这里看别人的思想,用并查集做的,建两个并查集,一个正向,一个反向,若正向能从a到b反向能从b到a则符合要求,然后这里并查集合并的时候要注意一点。
#include
#include
#define maxn 10000+10
int rec[3][maxn];
int n,m;
void init()
{
for(int i=1;i<=2;++i)
{
for(int j=1;j<=n;++j)
rec[i][j]=j;
}
}
int find(int x,int i)
{
return x==rec[i][x]?x:rec[i][x]=find(rec[i][x],i);
}
void merge(int a,int b)
{
if(a!=n)
{
int fa=find(a,1);
int fb=find(b,1);
if(fa!=fb)
rec[1][a]=b;//合并到后面的那个元素身上
}
if(b!=n)
{
int fa=find(a,2);
int fb=find(b,2);
if(fa!=fb)
rec[2][b]=a;//合并到前面的那个元素上
}
}
int main()
{
int a,b;
while(scanf("%d%d",&n,&m)&&(n||m))
{
int flag=1;
init();
for(int i=1;i<=m;++i)
{
scanf("%d%d",&a,&b);
merge(a,b);
}
for(int i=1;i<=n;++i)
{
if(find(i,1)!=n||find(i,2)!=n)
{
flag=0;
break;
}
}
if(flag)
puts("Yes");
else
puts("No");
}
return 0;
}
其实这题是可以用强连通分量写的,然而我还木弄懂那个tarjan算法,然而现在这个kosaraju超时。。。
//超时。。。
#include
#include
#define maxn 10000+10
using namespace std;
int n,m;
bool flag[maxn];//访问标志数组
int belg[maxn];//其中belg[i]表示顶点i属于第belg[i]个强连通分量
int numb[maxn];//结束时间标记,其中numb[i]表示离开时间为i的顶点
int cnt,rcnt;
int head[maxn],rhead[maxn];
void init()
{
memset(head,-1,sizeof(head));
memset(rhead,-1,sizeof(rhead));
cnt=rcnt=0;
}
struct node
{
int u,v,next;
};
node edge[maxn];
node redge[maxn];
void add(int u,int v)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void radd(int u,int v)//逆邻接表
{
redge[rcnt].u=u;
redge[rcnt].v=v;
redge[rcnt].next=rhead[u];
rhead[u]=rcnt++;
}
void visone(int cur,int &sig)//用于第一次深搜,求得numb[1..n]的值
{
flag[cur]=true;
for(int i=head[cur];i!=-1;i=edge[i].next)
{
if(flag[edge[i].v]==false)
visone(edge[i].v,sig);
}
numb[++sig]=cur;
}
void vistwo(int cur,int sig)//用于第二次深搜,求得belg[1..n]的值
{
flag[cur]=true;
belg[cur]=sig;
for(int i=rhead[cur];i!=-1;i=redge[i].next)
{
if(flag[redge[i].v]==false)
vistwo(redge[i].v,sig);
}
}
int kosaraju()//Kosaraju算法,返回为强连通分量个数
{
int i,sig;
memset(flag+1,0,sizeof(flag));
for(sig=0,i=1;i<=n;++i)
{
if(flag[i]==false)
visone(i,sig);
}
memset(flag+1,0,sizeof(flag));
for(sig=0,i=n;i>0;--i)
{
if(flag[numb[i]]==false)
vistwo(numb[i],++sig);
}
/* for(int i=1;i<=n;++i)
printf("%d ",belg[i]);
printf("\n");*/
return sig;
}
int main()
{
int a,b;
while(scanf("%d%d",&n,&m)&&(n+m))
{
init();
while(m--)
{
scanf("%d%d",&a,&b);
add(a,b);
radd(b,a);
}
int t=kosaraju();
if(t>1)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}