给一个图,问若从0号点开始走,能不能一条路径走完所有的边。
这个题WA了好多次。
一开始的时候没读清楚,一个路径?什么是一个路径?开始写了个每个点只走一次的,WA了。
然后,一个路径?又写了个每条边都走一次的,WA了。
次奥!!
然后开始看discusss之类的东西,原来一个路径就是一条路不停地走,可以回去,边也可以走N次,就是看一看能不能一条道走完所有边就可以了。
这样的话,一个强连通分量就可以当做一个点来处理,这样原来的图就变成了一个DAG。
写完这里还是WA。
为什么呢?
...原来是我缩点的时候如果两个强联通分量间有多条边相连的话我只算了一条,这里的缩点其实并不是真的要缩点,问题还是要看实际意义的,这里边的条数就不能减少。
再次修改,A了。
也是第一次写tarjan,需要初始化的东西有点多啊。看样子可以写个init函数。
还有,tarjan完全不必要另开一个数组used来记录点是否被遍历过,直接给DFN赋值成-1就好了。
#include<stdio.h>
#include<queue>
#include<string.h>
#include<map>
#include<stack>
using namespace std;
vector<int> G[2000];
vector<int> C[2000];
int dfn[2000];
int low[2000];
int cmp[2000];
stack<int> sta;
bool instack[2000];
bool used[2000];
int topo[2000];
map<int,int> mp;
int time=0;
int nv;
int ncmp=0;
int ans=0;
void tarjan(int n)
{
used[n]=1;
dfn[n]=low[n]=time++;
sta.push(n);
instack[n]=1;
for(int i=0;i<G[n].size();i++)
{
int v=G[n][i];
if(!used[v])
{
tarjan(v);
if(low[v]<low[n])
low[n]=low[v];
}
else
{
if(instack[v]&&dfn[v]<low[n])
low[n]=dfn[v];
}
}
if(dfn[n]==low[n])
{
int v;
do
{
v=sta.top();
sta.pop();
instack[v]=false;
cmp[v]=ncmp;
}while(v!=n);
ncmp++;
}
}
void sccDfs()
{
for(int i=0;i<nv;i++)
{
for(int j=0;j<G[i].size();j++)
{
int v=G[i][j];
int cv=cmp[v];
int cn=cmp[i];
if(cn!=cv)
{
C[cn].push_back(cv);
}
}
}
}
void addEdge(int f,int t)
{
if(mp.find(f)==mp.end())
mp[f]=nv++;
f=mp[f];
if(mp.find(t)==mp.end())
mp[t]=nv++;
t=mp[t];
G[f].push_back(t);
}
void printG(vector<int> GG[])
{
for(int i=0;i<nv;i++)
{
printf("%d: ",i);
for(int j=0;j<GG[i].size();j++)
printf("%d ",GG[i][j]);
printf("\n");
}
}
int in[2000];
int out[2000];
int main()
{
int cas;
scanf("%d",&cas);
for(int T=1;T<=cas;T++)
{
ans=0;
nv=0;
ncmp=0;
ne=0;
mp.clear();
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(used,0,sizeof(used));
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(G,0,sizeof(G));
memset(C,0,sizeof(C));
memset(e,0,sizeof(e));
time=0;
for(int i=0;i<2000;i++)
{
dfn[i]=-1;
cmp[i]=-1;
}while(!sta.empty()) sta.pop();
int k;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
int n;
scanf("%d",&n);
for(int j=0;j<n;j++)
{
int f,t;
scanf("%d%d",&f,&t);
addEdge(f,t);
}
}
int start;
if(mp.find(0)==mp.end())
{
printf("Case %d: NO\n",T);
continue;
}
start=mp[0];
for(int i=0;i<nv;i++)
if(!used[i])
tarjan(i);
memset(used,0,sizeof(used));
time=0;
printf("Case %d: ",T);
if(ncmp==1)
{
puts("YES");
continue;
}
int cnt1=0,cnt2=0,cnt3=0;
/*
for(int i=0;i<nv;i++)
{
for(int j=0;j<G[i].size();j++)
{
int v=G[i][j];
int cn=cmp[i];
int cv=cmp[v];
if(cn!=cv)
{
out[cn]++;
in[cv]++;
}
}
}
*/
sccDfs();
for(int i=0;i<ncmp;i++)
{
for(int j=0;j<C[i].size();j++)
{
int v=C[i][j];
in[v]++;
out[i]++;
}
}
for(int i=0;i<ncmp;i++)
{
if(in[i]==0&&out[i]==1) cnt1++;
if(in[i]==1&&out[i]==1) cnt2++;
if(in[i]==1&&out[i]==0) cnt3++;
}
if(in[cmp[start]]!=0||out[cmp[start]]==0)
{
puts("NO");
continue;
}
if(cnt1==1&&cnt3==1&&ncmp==cnt1+cnt2+cnt3)
puts("YES");
else
puts("NO");
}
return 0;
}