题目背景
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行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。
输入输出样例
输入样例#1:
9
1 2
2 3
3 4
4 2
4 5
2 5
5 6
5 7
4 6
输出样例#1:
1
2
3
4
2
5
4
6
5
7
题解:
一看描述就是欧拉回路对不对....可我特么就是写不对!写那种暴力回溯又过的点不多.于是这道题被张老师推荐了一个很牛B的算法.其实我也是真的不知道这个算法咋实现的...但作为模板它真的极为简单,我个人认为是蛮好背的....以下是代码.
PS:这个算法的名字叫做Hierholzer.想学习欧拉路务必查查这个.
另外欧拉路这个东西的起点必然是从出度为奇数,入读亦为奇数.(其实入读为奇数就很OK,但官方说法如此我也没办法!)
另外很悲伤的一件事情是这个节点标号得记最小最大值,因为不是按顺序的.核心代码就是这样...递归回来直接加入路径,倒序输出即为答案..。PSS:记得路径是可以重复,所以必须记出现次数,到0才退才退!!!
有同学可能对这个if语句有点疑问,改成while是不是才是对的,其实我觉得并不,原因很简单,它会被再次搜索到,因为所有栅栏联通(完全图)所以必然还是会走到的.当然,while也是对的
#include
using namespace std;
int map[505][505];
int path[1050];
int pathnum;
int minv=0x7ffff,maxv=0;
void Ec(int v)
{
for(int i=minv;i<=maxv;i++)
{
if(map[i][v]>0)
{
map[i][v]--;
map[v][i]--;
Ec(i);
}
}
path[pathnum++]=v;
}
int main()
{
int f;
int i,j,k;
cin>>f;
for(i=0;i>a>>b;
minv=min(a,minv);
minv=min(b,minv);
maxv=max(a,maxv);
maxv=max(b,maxv);
map[a][0]++;
map[b][0]++;
map[a][b]++;
map[b][a]++;
}
k=minv;
for(int i=minv;i<=maxv;i++)
{
if(map[i][0]%2==1)
{
k=i;
break;
}
}
Ec(k);
for(i=pathnum-1;i>=0;i--)
{
cout<