歐拉回路&【洛谷習題】無序字母對
首先非常痛心疾首地說一句,歐拉回路自己之前只是看過代碼,知道思想,從來沒有親手實現過,所以,,,傷亡慘重!!!
歐拉回路是一個非常有意思的圖論模型,因為偉大的數學家歐拉(euler)而得名。傳說,曾經人們沈迷於一個七橋問題,想找出一種走法不重復地經過七座橋(具體請自行了解)。歐拉指出了不存在這樣的走法,並由此歸結出了“一筆畫問題”。用圖論的語言來說,就是找一條路徑不重復地走過所有的邊。
實際上,從一個點出發,不重復地經過所有的邊,這叫做歐拉道路;如果這條路徑起點和終點相同,才稱為歐拉回路。另外,如果一個圖存在歐拉道路,那麽稱為半歐拉圖,如果一個圖存在歐拉回路,稱為歐拉圖。
對於無向圖,存在歐拉道路的條件是只有兩個或不存在奇點(度為奇數的點),存在歐拉回路的條件是不存在奇點。對於有向圖,存在歐拉道路的條件是只有兩個點的入度和出度不相同,並且其中一個點(起點)的出度比入度大1,另一個點(終點)的入度比出度大1,或者所有點的入度和出度都相等,存在歐拉回路的條件是所有點的入度和出度都相等。當然圖必須是連通的。
尋找歐拉道路或者歐拉回路是比較簡單的,可以使用DFS。起點的確定也需要註意,如果找歐拉道路,必須找到相應的起點,而歐拉回路任選一個點作為起點即可。
1 void euler(int u) { 2 for(int v=1;v<=n;++v)尋找歐拉道路或歐拉回路(無向圖)3 if(G[u][v]) { 4 G[u][v]=G[v][u]=0; //有向圖則改為G[u][v]=0; 5 euler(v); 6 } 7 ans.push(u); 8 }
需要註意的是,我們此處標記的是邊(或者刪除邊)。因為歐拉道路或歐拉回路是可以一口氣走到結束的,所以上面的代碼可以放心寫個循環,且遞歸後不必跳出,因為當返回該點時,該點所連的其他邊必然已經被走過了。因此答案裏存的就是一條完整的路徑。
無序字母對:https://www.luogu.org/problemnew/show/P1341
這道題的話,還是浪費了很多時間,一是因為歐拉回路以前沒寫過,而是因為這道題答案保存那裏有點玄學問題,默默改成棧就過了。字符的處理也需要註意一下。
1 #include<cstdio> 2 #include<stack> 3 using namespace std; 4 const int maxn=55; 5 int n,G[maxn][maxn],d[maxn]; 6 stack<int> ans; //用棧倒序保存答案 7 int toInt(char c) { //字符轉為整數 8 if(c>=‘A‘&&c<=‘Z‘) return c-‘A‘+1; 9 return c-‘a‘+27; 10 } 11 char toChar(int i) { //整數轉為字符 12 if(i>=1&&i<=26) return i-1+‘A‘; 13 return i-27+‘a‘; 14 } 15 void euler(int u) { 16 for(int v=1;v<=52;++v) 17 if(G[u][v]) { 18 G[u][v]=G[v][u]=0; //刪邊 19 euler(v); 20 } 21 ans.push(u); 22 } 23 int main() { 24 scanf("%d",&n); 25 char cu,cv; 26 int u,v; 27 for(int i=1;i<=n;++i) { 28 while((cu=getchar())==‘\n‘||cu==‘ ‘||cu==‘\r‘); //過濾無用字符 29 cv=getchar(); 30 u=toInt(cu),v=toInt(cv); 31 G[u][v]=G[v][u]=1; 32 ++d[u],++d[v]; //統計度數 33 } 34 int s=0,cnt=0; 35 for(int i=1;i<=52;++i) //找起點和判斷是否存在歐拉道路 36 if(d[i]&1) { 37 ++cnt; 38 if(!s) s=i; 39 } 40 if(!cnt) for(int i=1;i<=52;++i) 41 if(d[i]) { 42 s=i; 43 break; 44 } 45 if(cnt&&cnt!=2) { 46 printf("No Solution\n"); 47 return 0; 48 } 49 euler(s); 50 if((int)ans.size()<n+1) printf("No Solution"); 51 while(!ans.empty()) { 52 int p=ans.top(); 53 ans.pop(); 54 printf("%c",toChar(p)); 55 } 56 putchar(‘\n‘); 57 return 0; 58 }AC代碼
歐拉回路&【洛谷習題】無序字母對