骑马修栅栏
Time Limit:1000MS Memory Limit:65536K
Total Submit:91 Accepted:35
Description
农民
J
o
h
n
John
John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。
J
o
h
n
John
John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个一个栅栏。你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次。
J
o
h
n
John
John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。
每一个栅栏连接两个顶点,顶点用
1
1
1到
500
500
500标号(虽然有的农场并没有500个顶点)。一个顶点上可连接任意多
(
>
=
1
)
(>=1)
(>=1)个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。
你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。我们如果把输出的路径看成是一个
500
500
500进制的数,那么当存在多组解的情况下,输出
500
500
500进制表示法中最小的一个 (也就是输出第一个数较小的,如果还有多组解,输出第二个数较小的,等等)。
输入数据保证至少有一个解。
Input
第
1
1
1行: 一个整数
F
(
1
<
=
F
<
=
1024
)
F(1 <= F <= 1024)
F(1<=F<=1024),表示栅栏的数目
第
2
2
2到
F
+
1
F+1
F+1行: 每行两个整数
i
,
j
(
1
<
=
i
,
j
<
=
500
)
i,j(1 <= i,j <= 500)
i,j(1<=i,j<=500)表示这条栅栏连接i与j号顶点。
Output
输出应当有
F
+
1
F+1
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
解题思路
暖心科普
:
:
: 欧拉路&欧拉回路 ,存在欧拉回路的充要条件
:
:
:
1.
1.
1.一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。
思路:dfs搜索,不能再往下走便回溯,回溯时记录路径,回溯时不清除对边的标记,最后求出来的路径就是欧拉回路。
注:不能一边走一边记录。。。请自行画图理解
代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,a[1030][1030],p[1030*2],ans,minn=1000000000,maxx,st,d[1030],dep;
void dfs(int x){
for(int i=minn;i<=maxx;i++)
{
if(a[x][i]>0)
{
a[x][i]--;
a[i][x]--;
dfs(i);
//这里不用回溯
}
}
d[++dep]=x;//回溯记录答案
}
int main(){
scanf("%d",&n);
int xx,yy;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&xx,&yy);
a[xx][yy]++;//谁他妈知道两点之间有多条栅栏,让我WA了这么久。(要感谢ZZL大佬的扎心提示)
a[yy][xx]++;
p[xx]++; p[yy]++;//记录度
minn=min(minn,(min(xx,yy)));
maxx=max(maxx,(max(xx,yy)));
}
st=minn;
for(int i=minn;i<=maxx;i++)
{
if(p[i]%2!=0)//度为奇数
{
st=i;//设为起点
break;
}
}
dfs(st);
for(int i=dep;i>0;i--)
cout<<d[i]<<endl;//因为回溯才存,所以顺序是倒的
}