题目来源:http://acm.wust.edu.cn/problem.php?id=1923&soj=0
★我也不知道方法是不是特别好,但是能AC 233
附上同学的博客(比我简单,但不易懂) https://blog.csdn.net/qq_44684599/article/details/88694464
相关知识:
解决这个问题就要提到 瑞士数学家 欧拉–这位巨巨创立了图论
他发现的几个定理对这题很有帮助。
前提:一笔画的路径叫欧拉路;如果最后可以回到出发点,则这个路径叫欧拉回路;奇点指与这个点相连的边的数目为奇数的点。
定理1:若有2个奇点且图是连通的,则存在欧拉路
定理2:若没有奇点且图是连通的,则存在欧拉回路
错误代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
bool vis[maxn][maxn];
int degree[maxn];
int out[maxn];
int m,n,l;
void seek(int i)
{
out[++l]=i;
for(int j=1;j<=n;j++){
if(vis[i][j]){
vis[i][j]=vis[j][i]=0;
seek(j);
}
}
}
int main()
{
while(cin>>n>>m){
memset(vis,0,sizeof(vis));
memset(degree,0,sizeof(degree));
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
vis[x][y]=vis[y][x]=1;
degree[x]++;degree[y]++;
}
int num=l=0;
for(int i=1;i<=n;i++)
if(degree[i]%2) num++;
if(num==2){
int i;
for(i=1;i<=n;i++)
if(degree[i]%2) break;
seek(i);
}
else if(!num) seek(1);
else {cout<<"No Solution!\n"; continue;}
cout<<out[1];
for(int i=2;i<=l;i++) cout<<' '<<out[i];
cout<<endl;
}
}
错误原因请看下图
这种情况有多个欧拉回路,代码就出现了bug
思路:
先找奇点,奇点有2个则找到数小的那个开始;奇点有0个,则从1开始;其他个都没有结果;
找的时候通过回溯法(应该是叫回溯法叭),flag就是为了防止输出多个结果。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
bool vis[maxn][maxn];
int deg[maxn],ans[maxn];
int n,m;
bool flag;
void seek(int i,int step)
{
ans[step]=i;
if(!flag) return;
if(step==m+1){
for(int j=1;j<=m;j++)
cout<<ans[j]<<' ';
cout<<ans[m+1]<<endl;
flag=0;
return ;
}
for(int k=1;k<=n;k++){
if(vis[i][k]){
vis[i][k]=vis[k][i]=0;
seek(k,step+1);
vis[i][k]=vis[k][i]=1;
}
}
}
int main()
{
while(cin>>n>>m){
memset(vis,0,sizeof(vis));
memset(deg,0,sizeof(deg));
flag=1;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
vis[a][b]=vis[b][a]=1;
deg[a]++;deg[b]++;
}
int num=0;
for(int i=1;i<=n;i++){
if(deg[i]%2)
num++;
}
if(num==2){
int i;
for(i=1;i<=n;i++){
if(deg[i]%2)
break;
}
seek(i,1);
}
else if(!num) seek(1,1);
else {cout<<"No Solution!\n"; continue;}
}
}