题目:
题解:
就是个模板题啊
按理说应该有两种方法:
1、Kobalabala :从任意一个点开始,如果可以遍历到所有点,而且,反置边之后依然可以遍历到所有点那就是Yes 否则就是No(但这个方法蜜汁不对?)
2、Tarjan..........
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int tot,N,tmp,cnt,strack[10005],point[100005],nxt[200005],v[200005],Dfn[10005],Low[10005];
bool vis[10005];
void cl()
{
tot=0; memset(point,0,sizeof(point));
memset(v,0,sizeof(v));
memset(nxt,0,sizeof(nxt));
memset(Dfn,0,sizeof(Dfn));
memset(Low,0,sizeof(Low));
tmp=0; cnt=0;
}
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void tarjan(int now)
{
Dfn[now]=Low[now]=++N; strack[++tmp]=now; vis[now]=1;
for (int i=point[now];i;i=nxt[i])
if (!Dfn[v[i]])
{
tarjan(v[i]);
Low[now]=min(Low[now],Low[v[i]]);
}
else if (vis[v[i]]) Low[now]=min(Low[now],Dfn[v[i]]);
if (Low[now]==Dfn[now])
{
++cnt;
while (strack[tmp]!=now) vis[strack[tmp]]=0,tmp--;
vis[strack[tmp]]=0; tmp--;
}
}
int main()
{
int n,m,x,y;
while (~scanf("%d%d",&n,&m)){
if (!n&&!m) return 0;
cl();
for (int i=1;i<=m;++i)
scanf("%d%d",&x,&y),addline(x,y);
for (int i=1;i<=n;++i)
if (!Dfn[i]) tarjan(i);
if (cnt==1) printf("Yes\n");
else printf("No\n");
}
}