Description
Farmer John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。
John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个栅栏。你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次。John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。
每一个栅栏连接两个顶点,顶点用1到500标号(虽然有的农场并没有500个顶点)。一个顶点上可连接任意多(>=1)个栅栏。两顶点间可能有多个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。
你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。我们如果把输出的路径看成是一个500进制的数,那么当存在多组解的情况下,输出500进制表示法中最小的一个 (也就是输出第一位较小的,如果还有多组解,输出第二位较小的,等等)。
输入数据保证至少有一个解。
Input
第1行: 一个整数F(1 <= F <= 1024),表示栅栏的数目
第2到F+1行: 每行两个整数i, j(1 <= i,j <= 500)表示这条栅栏连接i与j号顶点。
Output
输出应当有F+1行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。
Sample Input
9 1 2 2 3 3 4 4 2 4 5 2 5 5 6 5 7 4 6
Sample Output
1 2 3 4 2 5 4 6 5 7
说明
题目翻译来自NOCOW。
USACO Training Section 3.3
题解
欧拉路径的模板题了吧
预备知识:
欧拉回路:从一个点可以遍历整张图,最后回到原来的点
欧拉通路:从一个点可以遍历整张图,最后回不到原来的点
对于无向图而言:(大前提:图联通
欧拉回路:任意点的度数为偶 起点可随意
欧拉通路:有且仅有两个点度数为奇 在遍历时一定要从一个为奇的点到另一个为奇的点
对于有向图:(还是大前提图联通
欧拉回路:每个点入度==出度
欧拉通路:有且仅有一个点出度-入度==1 为起点;有且仅有一个点入度-出度==1 为终点; 其余的点出度==入度
然后这道题的解法和算法学习都借鉴了排名第一的题解Misaka_Azusa的题解
所以是Hierholzers算法啦!
双向存边,记录每个点的度。
从小到大扫一遍 找有没有度数为奇的点 若有则break,从当前点开始dfs(欧拉通路
如果所有点度为偶则从最小的点开始dfs(欧拉回路
1 stack<int>st; 2 void dfs(int x) 3 { 4 for(int v=l;v<=r;++v) 5 if(tu[x][v]) 6 { 7 tu[x][v]--; 8 tu[v][x]--; 9 dfs(v); 10 } 11 st.push(x); 12 return; 13 }
看代码然后强行理解应该就够了
然后对于stack 一开始自作聪明的成在开头直接输出QAQ
如果有一样的危险想法,讨论区给的这个样例还是蛮助于理解的
1 6 2 1 2 3 2 3 4 3 4 5 3 5 6 3 6 7 5 6
以下是全代码
1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 #include<cmath> 5 using namespace std; 6 int du[507]; 7 int tu[507][507]; 8 int l,r; 9 stack<int>st; 10 void dfs(int x) 11 { 12 for(int v=l;v<=r;++v) 13 if(tu[x][v]) 14 { 15 tu[x][v]--; 16 tu[v][x]--; 17 dfs(v); 18 } 19 st.push(x); 20 return; 21 } 22 int main() 23 { 24 int f; 25 scanf("%d",&f); 26 l=9999,r=0; 27 for(int i=1;i<=f;++i) 28 { 29 int x,y; 30 scanf("%d%d",&x,&y); 31 tu[x][y]++; 32 tu[y][x]++; 33 du[x]++; 34 du[y]++; 35 l=min(l,x); 36 l=min(l,y); 37 r=max(r,x); 38 r=max(r,y); 39 } 40 int s=l; 41 for(int i=l;i<=r;++i) 42 if(du[i]%2==1){s=i;break;} 43 dfs(s); 44 while(!st.empty()) 45 { 46 printf("%d ",st.top()); 47 st.pop(); 48 } 49 return 0; 50 }
YJQ说这是集训队算法(逃