题意:
给你一个无向图,数据格式如点x 点y 边Z,表示由x点和y点构成了Z边。现在要问你该图中是否存在欧拉回路,如果存在,则输出字典序最小的那条欧拉回路(输入按序走过的所有边标号)。且题目中保证了该无向图是连通。
思路:
使用欧拉路径输出模板来进行输出即可。然后要保证从John的家作为起始点输出欧拉回路且保证字典序最小,因为euler这个函数输出的欧拉路径是从起点逆序的(即起点被放到了最后才输出),所以我们需要把最后结果保存在ans数组中,最后逆序输出,且每次都是从小到大选择与当前节点相连的可行边的(这样可以保证输出结果的字典序最小。注意,应该首先进行判断是否能组成欧拉回路,即所有点的度数均为偶数。
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=20000 ;
int n,m;
int degree[maxn];//记录度
int vis[maxn];
int ans[maxn];//记录边
int cnt;
struct Edge{
int u;
int v;
}edge[maxn];
bool ok(){ //判断能否组成欧拉回路
for(int i=1;i<=n;i++) if(degree[i]%2) return false;
return true;
}
void euler(int s){ //关键部分
for(int i=1;i<=m;i++) if(!vis[i]&&(edge[i].u==s||edge[i].v==s)){//此处从小到大,保证了字典序
vis[i]=1;
euler(edge[i].u+edge[i].v-s);
ans[cnt++]=i;
}
}
int main()
{
int x,y,z;
while(scanf("%d%d",&x,&y)==2&&x){
cnt=n=m=0;
memset(degree,0,sizeof(degree));
memset(vis,0,sizeof(vis));
int start=min(x,y);
do{
scanf("%d",&z);
edge[z].u=x;
edge[z].v=y;
degree[x]++;
degree[y]++;
m++;
n=max(n,max(x,y));
}while(scanf("%d%d",&x,&y)==2&&x);
if(!ok()){
printf("Round trip does not exist.\n");
continue;
}
euler(start);
printf("%d",ans[m-1]);
for(int i=m-2;i>=0;i--){
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}
地址:
点击打开链接