题目背景
Farmer John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。
题目描述
John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个栅栏。你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次。John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。
每一个栅栏连接两个顶点,顶点用1到500标号(虽然有的农场并没有500个顶点)。一个顶点上可连接任意多(>=1)个栅栏。两顶点间可能有多个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。
你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。我们如果把输出的路径看成是一个500进制的数,那么当存在多组解的情况下,输出500进制表示法中最小的一个 (也就是输出第一位较小的,如果还有多组解,输出第二位较小的,等等)。
输入数据保证至少有一个解。
输入输出格式
输入格式:
第1行: 一个整数F(1 <= F <= 1024),表示栅栏的数目
第2到F+1行: 每行两个整数i, j(1 <= i,j <= 500)表示这条栅栏连接i与j号顶点。
输出格式:
输出应当有F+1行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。
求欧拉路的问题,应该先判断图中是否存在欧拉路(奇点的个数是否大于2,当然本题保证图中存在欧拉路),然后题中要求按照字典序大小来求,所以不能从任意节点出发,先判断是否存在奇点,若存在,从两个奇点中编号较小的那一个出发,若不存在,从所有节点中编号最小的一个出发。注意一点,节点的上限是500,但路径数目并没有上限(因为两个节点之间可能存在多条路径),所以存储答案的数组要足够大,只开500会WA(提交20多次就卡这一个点...)
#include<iostream> #include<cstring> using namespace std; ],can[][],res[],iindex=,n,mmax=; void dfs(int u) { ;i<=mmax;i++) if(can[u][i]) { can[u][i]--; can[i][u]--; dfs(i); } ++iindex;res[iindex]=u; } int main() { ,from,to; cin>>n; memset(count,,sizeof(count)); memset(can,,sizeof(can)); mmax=; while(n--) { cin>>from>>to; can[from][to]++; can[to][from]++; count[from]++; count[to]++; mmax=max(mmax,max(from,to)); start=min(start,min(from,to)); } ;i<=mmax;i++) { ==) { dfs(i); while(iindex) cout<<res[iindex--]<<endl; ; } } dfs(start); while(iindex) cout<<res[iindex--]<<endl; ; }