#include<iostream>
#include<string.h>
using namespace std;
int f[1050][1050],d[1050],res[1550000];
int n,j=0,k=0,m=0;
void search(int z)
{
for(int i=1;i<=m;i++)
if(f[z][i]>0)
{f[z][i]--;
f[i][z]--;
search(i);
}
j++;
res[j]=z;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
{ int x,y;
cin>>x>>y;
f[x][y]++;
f[y][x]++;
d[x]++;d[y]++;
m=max(max(x,m),y);
}
for(int i=1;i<=m;i++)
if(d[i]%2!=0)
{k=i;break;}
if(k==0)
{
for(int i=1;i<=n;i++)
if(d[i])
{k=i;break;}}
search(k);
for(int i=j;i>0;i--)
cout<<res[i]<<endl;
return 0;
}
本渣写的该题的程序。思路大致是剽窃wikioi上本题的某位选手的。
现在,让我来重温思路,加强理解 ,巩固记忆。
f[x][y]++;
f[y][x]++; 这两句很妙,和后面的减减堪称是本算法的点睛之笔(个人拙见,勿喷)。该句话是记录出现过的路径,有的就标为1.而函数中的减减,则是该路已走过一次后,便标为0,使得不会重复走。理解了这一点,该算法便理解大半了。
d[x],d[y]是记录该点一共有几条线(好像叫出线?)来辨认奇度点和偶度点(出线为奇或偶)。
m=max(max(x,m),y);至于这一句,则是在记录出现的点的最大值,确定点的范围。
for(int i=1;i<=m;i++)
if(d[i]%2!=0)
{k=i;break;}
if(k==0)
{
for(int i=1;i<=n;i++)
if(d[i])
{k=i;break;}} 这一句这是寻找有没有奇度点(不明白奇度点对于欧拉回路的含义可自行百度),有奇度点就记录小的奇度点。没有则记录最小的偶度点。
然后,找到了最小的奇(偶)度点,就可以开始运用函数啦!
void search(int z)
{
for(int i=1;i<=m;i++)
if(f[z][i]>0)
{f[z][i]--;
f[i][z]--;
search(i);
}
j++;
res[j]=z;
} 从最小的奇(偶)度点开始,寻找点的大小和它最接近的点组成的线,然后再把该线记录为0,避免重复。下面的J++是记录该点出现的第几次数。
用res[]保存。
至于最后面为啥要倒序输出,我还不懂,。等懂了我再来补上。
欢迎高人指点,鄙人实乃新手。
欧拉回路-骑马修栅栏