poj 1041
這個題比較難,然後我也不懂,看了看別人的題解,算是懂了點,但仍然感覺思路不是很清楚
看看http://www.cnblogs.com/ylfdrib/archive/2010/08/24/1807602.html
這個講的比較好
這道題很不錯,由於圖已經保證連通,首先用度數是否是偶數,判斷圖是否是歐拉圖,然後,輸出最小升序,就成了一大難題,百科上有代碼,這題讓我理解了深搜的又一強大功能,其實就是每次都從小往大的搜,先搜得一個最小序環,然後對環上的每一點進行搜索,其實對於歐拉圖而言,每個點要麼就只剩一個點,什麼也搜不到了,要麼還有一個環,只要把環上路徑全都插入到對應位置上,用棧存路徑,每次只有回溯到當前點,就是說當前點的後繼都已經搜過了的時候,才把當前點入棧,這樣一來倒着輸出,就能得到一個歐拉回路,而且是最小升序。
就是這樣一個代碼,就能實現歐拉回路的輸出,唯一一點特別的就是,stk[++top] = e,是在v點搜完了才執行的,想想就知道這有什麼含義,這樣纔是真正的最小序歐拉回路。實現代碼見下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 10 ;
int Map[maxn][maxn];//Map[u][z]=v,表示u通過邊Z與v相連
int adj[maxn][maxn];//adj[u][i]=z,表示u的第i條邊爲z
int vis[maxn];
int num[maxn];
int st[maxn];// ji lu lu jing
int idx,S,top;
int cmp(const void *a,const void *b){
return *(int *)a-*(int *)b;
}
void dfs(int u){
int i,v,e;
for(int i=1;i<=num[u];i++){
e=adj[u][i];
if(!vis[e]){
v=Map[u][e];
vis[e]=1;
dfs(v);
st[++top]=e;
}
}
}
void ori(){
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
memset(Map,0,sizeof(Map));
memset(st,0,sizeof(st));
top=0;
}
int main(){
int a,b,z;
while(~scanf("%d%d",&a,&b)){
if(a==0&&b==0)break;
ori();
S=min(a,b);
scanf("%d",&z);
adj[a][++num[a]]=z;
adj[b][++num[b]]=z;
Map[a][z]=b;
Map[b][z]=a;
while(scanf("%d%d", &a, &b) != EOF){
if (a == 0 && b == 0) break;
scanf("%d", &z);
adj[a][++num[a]] = z;
adj[b][++num[b]] = z;
Map[a][z] = b;
Map[b][z] = a;
}
int i;
for(i=1;;i++){
if(num[i]==0)break;
if(num[i]%2)break;
}
if(num[i]!=0){printf("Round trip does not exist.\n");continue;}
int maxN=i-1;
for(i=1;i<=maxN;i++){
qsort(adj[i]+1,num[i],sizeof(int),cmp);
}
dfs(S);
for(int i=top;i>1;i--)printf("%d ",st[i]);
printf("%d\n",st[1]);
}
}