思路:点双连通。。先贴个代码,马上实验室锁门,下次详解吧
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
struct query
{
int num;
int v;
};
struct edge
{
int u,v;
};
stack<edge>st;
vector<query>g[5005];
int n,m,q;
int du[1005],dv[1005];
int block,num,scnum;
int ans[1005];
int fst[5005],next[20005],node[20005],en;
int dfn[5005],low[5005];
int d[5005];
int b[5005];
bool ve[20005];
void init()
{
en=0;
block=0;
num=0;
scnum=0;
memset(fst,-1,sizeof(fst));
memset(dfn,0,sizeof(dfn));
memset(ans,0,sizeof(ans));
memset(d,0,sizeof(d));
memset(ve,0,sizeof(ve));
for(int i=0;i<n;i++)g[i].clear();
}
void add(int u,int v)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
en++;
}
void check(edge temp)
{
if(st.top().u==temp.u&&st.top().v==temp.v)
{
st.pop();
return;
}
scnum++;
edge ed;
do
{
ed=st.top();
st.pop();
d[ed.u]=scnum;
d[ed.v]=scnum;
int u=ed.u;
int size=g[u].size();
for(int i=0;i<size;i++)
{
if(dfn[g[u][i].v]&&ans[g[u][i].num]==0)
{
if(d[u]==d[g[u][i].v])
{
ans[g[u][i].num]=2;
}
}
}
}while((ed.u!=temp.u)||(ed.v!=temp.v));
}
void tarjan(int u,int r)
{
b[u]=block;
dfn[u]=low[u]=++num;
for(int i=fst[u];i!=-1;i=next[i])
{
int v=node[i];
if(v==r||ve[i])continue;
ve[i]=ve[i^1]=1;
edge ed;
ed.u=u;
ed.v=v;
st.push(ed);
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<=low[v])
{
check(ed);
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
int ca=1;
int u,v;
while(scanf("%d%d%d",&n,&m,&q))
{
if(n==0&&m==0&&q==0)break;
init();
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=0;i<q;i++)
{
scanf("%d%d",&u,&v);
du[i]=u;
dv[i]=v;
query qq;
qq.num=i;
qq.v=v;
g[u].push_back(qq);
qq.v=u;
g[v].push_back(qq);
}
for(int i=0;i<n;i++)
{
++block;
if(!dfn[i])tarjan(i,-1);
}
cout<<"Case "<<ca++<<":"<<endl;
for(int i=0;i<q;i++)
{
if(ans[i]==2)cout<<"two or more"<<endl;
else
{
if(b[du[i]]==b[dv[i]])
{
cout<<"one"<<endl;
}
else cout<<"zero"<<endl;
}
}
}
return 0;
}
/*
5 6 10
0 1
0 2
1 2
2 3
2 4
3 4
0 1
0 2
0 3
0 4
1 2
1 3
1 4
2 3
2 4
3 4
*/