题目大意:有n个珠子,珠子两边的颜色已知,问能否连成一条项链。(两个珠子可以项链当且仅当一个珠子的一边颜色与另一个珠子的另一边颜色相同)。

题目分析:欧拉回路。将颜色视作节点,珠子当做边,问题变成了找一条欧拉回路。

欧拉回路存在的条件:无向图:1.图连通;2.无奇点;  有向图:1.忽略边的方向后,图连通;2.每个点的入度都等于出度;

注意:输出回路的时候要逆序输出。。。

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std; int n,du[55],v[55][1005],mp[55][55],vis[55]; void dfs(int u)
{
for(int i=1;i<=v[u][0];++i){
int k=v[u][i];
if(!vis[k]){
vis[k]=1;
dfs(k);
}
}
} bool judge()
{
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1;i<=50;++i){
if(du[i]==0)
continue;
if(!vis[i]){
++cnt;
if(cnt>1)
return false;
vis[i]=1;
dfs(i);
}
}
for(int i=1;i<=50;++i)
if(du[i]&1)
return false;
return true;
} void print(int u)
{
for(int i=1;i<=v[u][0];++i){
int k=v[u][i];
if(!mp[u][k])
continue;
--mp[u][k],--mp[k][u];
print(k);
printf("%d %d\n",k,u);///逆序输出
}
} int main()
{
int T,a,b,cas=0;
scanf("%d",&T);
while(T--)
{
memset(du,0,sizeof(du));
memset(mp,0,sizeof(mp));
scanf("%d",&n);
for(int i=0;i<55;++i)
v[i][0]=0;
while(n--)
{
scanf("%d%d",&a,&b);
v[a][++v[a][0]]=b;
v[b][++v[b][0]]=a;
++du[a],++du[b];
++mp[a][b],++mp[b][a];
}
printf("Case #%d\n",++cas);
if(!judge())
printf("some beads may be lost\n");
else{
for(int i=1;i<=50;++i){
if(du[i]>0){
print(i);
break;
}
}
}
if(T)
printf("\n");
}
return 0;
}

  

05-11 18:12