[luogu1341][無序字母對]
阿新 • • 發佈:2018-10-14
ont targe for get 倒序輸出 -i n-2 分享 stream
luogu1341
思路
歐拉回路和歐拉路的裸題,首先判斷是否存在歐拉路或者歐拉回路。當且僅當途中每個點的度數都為偶數時,存在歐拉回路。當且僅當圖中度數為奇數的點的個數為2時,存在歐拉路。如果存在歐拉回路,就可以找一個最小的點開始dfs。如果存在歐拉路,那就只能從度數為奇數的兩個點中更小的那個開始dfs。
歐拉回路的dfs過程大概就是一邊刪邊,一邊dfs。
如圖,dfs的過程大概就是
1-2
2-3
3-6
6-5
5-4
4-1
1入隊,返回
4入隊,返回
5入隊,返回
6-7
7-9
8-10
10-11
11-9
9-6
6入隊,返回
9入隊,返回
11入隊,返回
10入隊,返回
8入隊,返回
7入隊,返回
6入隊,返回
3入隊,返回
2入隊,返回
1入隊,結束
此時隊列中剛是(1-4-5-6-9-11-10-8-7-6-3-2-1),就是一個合法的歐拉回路了。因為題目中要求按照字典序最小輸出序列,所以每次搜索的時候先搜索字典序小的。然後將隊列倒序輸出才可以。
因為要按字典序從小到大搜索,所以鄰接表似乎就有點麻煩了。所以直接用鄰接矩陣。
代碼
#include<cstdio> #include<iostream> using namespace std; const int N = 1000; int du[N],e[N][N],ji[N],ans[N*10],ansjs; char c[5]; void dfs(int u) { for(int i = 'A';i <= 'z';++i) { if(!e[u][i]) continue; e[u][i]--; e[i][u]--; dfs(i); } ans[++ansjs]=u; } int main() { int n; scanf("%d",&n); for(int i = 1;i <= n;++i) { scanf("%s",c+1); e[int(c[1])][int(c[2])]++; e[int(c[2])][int(c[1])]++; du[int(c[1])]++; du[int(c[2])]++; } int js=0; for(int i = 'A';i <= 'z';++i) if(du[i]&1) ji[++js]=i; if(js != 0 && js != 2) { puts("No Solution"); return 0; } int s=1000; for(int i = 'A';i <= 'z';++i) { if(!du[i]) continue; if(js == 0) s=min(s,i); else if(du[i]&1) s=min(s,i); } dfs(s); for(int i = ansjs;i >= 1;--i) printf("%c",ans[i]); return 0; }
[luogu1341][無序字母對]