John's Trip
【题目描述】
John想要拜访每一位朋友,他的朋友住在不同的街道上,每一条道路他只能走一次。
他想要从家出发,拜访完所有的朋友后回到自己家,且行走的总路程最短。
【输入描述】
输入多组数据,每组数据输入格式如下:
输入若干行,每行包含三个整数X、Y、Z,分别代表这条街( <= 1995)连接的两个路口( <= 44)的编号(实际数据中可能是自环),以及这条街的编号。John住在数据第一行表示的街道连接的两个顶点中编号较小的路口处,所有的街道都可以连通到其他街道上;
输入“0 0”表示一组数据的结束;
最后一行输入“0 0”表示输入结束。
【输出描述】
对于每组测试数据,如果能够找到答案,则输出找到的路径,如果不存在,输出“Round trip does not exist.”。
【输入样例】
1 2 1
2 3 2
3 1 6
1 2 5
2 3 3
3 1 4
0 0
1 2 1
2 3 2
1 3 3
2 4 4
0 0
0 0
【输出样例】
1 2 3 5 4 6
Round trip does not exist.
源代码: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int Start,t,t1,t2,Top,Num[45],Step[1995],Map[45][1995],Edge[45][1995]; bool Mark[1995]; void DFS(int t) //搜索就一定能找出欧拉回路路线。 { for (int a=1;a<=Num[t];a++) { int S=Edge[t][a]; if (!Mark[S]) { int T=Map[t][S]; Mark[S]=true; DFS(T); Step[++Top]=S; } } } int main() //无向图求欧拉回路。 { while (scanf("%d%d",&t1,&t2)!=EOF) { if (!t1&&!t2) break; memset(Num,0,sizeof(Num)); //Num[]存储着某节点直连边的总数。 scanf("%d",&t); Start=min(t1,t2); //起点。 Edge[t1][++Num[t1]]=t; //Edge[]存储着某节点的直连边。 Edge[t2][++Num[t2]]=t; Map[t1][t]=t2; //Map[]存储着某节点通过某边到达的某节点。 Map[t2][t]=t1; while (scanf("%d%d",&t1,&t2)!=EOF) { if (!t1&&!t2) break; scanf("%d",&t); Edge[t1][++Num[t1]]=t; Edge[t2][++Num[t2]]=t; Map[t1][t]=t2; Map[t2][t]=t1; } int T; //妙用变量。 for (T=1;;T++) if (!Num[T]||Num[T]&1) //到达尽头或为奇数。 break; if (Num[T]) //按照欧拉回路,所有点出度应皆为偶数。 { puts("Round trip does not exist."); continue; } int Max=T-1; //注意,这时候是最大的节点编号。 for (T=1;T<=Max;T++) sort(Edge[T]+1,Edge[T]+Num[T]+1); //按编号给每个点的直连边排序。 memset(Mark,0,sizeof(Mark)); Top=0; DFS(Start); for (T=Top;T>1;T--) //输出路线时注意顺序。 printf("%d ",Step[T]); printf("%d\n",Step[T]); } return 0; }