UVa 10129 單詞(DFS判斷連通性)
阿新 • • 發佈:2018-12-13
題意:輸入N個單詞,N < 100000,是否可以把所有這些單詞排成一列,使得每個單詞的第一個字母和最後一個字母相同。每個單詞最多有1000個字母,輸入可能有重複的單詞。
思路: 1、把字母當成結點,單詞看做有向邊,問題有解當且僅當圖中存在歐拉回路。有向圖判斷存在歐拉回路的條件有兩個:(1)把圖看做無向圖,圖是連通的(DFS訪問,若存在未訪問的,則是不連通的) ;(2)最多有兩個點入度不等於出度,其中一個是起點,一個是終點。
2、每行輸入的資料只需記錄首字母和最後一個字母,然後轉化為數字,因此陣列只需開到26記錄26個字母對應的數字即可。
程式碼如下:
#include<cstdio> #include<cstring> const int maxn = 1000 + 10; int G[27][27],in[27],out[27],N,num[27]; void read() //讀入資料 { memset(G,0,sizeof(G)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); scanf("%d",&N); char s[maxn]; int first,last; while(N--) { scanf("%s",s); first = s[0] - 'a'; last = s[strlen(s)-1] - 'a'; G[first][last]++; in[last]++; out[first]++; } } void dfs(int i) { num[i] = 1; for(int j = 0;j < 26;j++) { if((G[i][j] > 0 || G[j][i] > 0) && num[j] == 0) { dfs(j); } } return; } bool judge_connect() //判斷連通性 { memset(num,0,sizeof(num));//儲存訪問情況 for(int i = 0;i < 26;i++) { if(out[i] > 0) { dfs(i); break; } } for(int i = 0;i < 26;i++) { if((in[i] > 0 || out[i] > 0) && num[i] == 0) { return false; } } return true; } bool judge_deg() //判斷度數情況 { int i,start = 0,end = 0; for(i = 0;i < 26;i++) { if(in[i] != out[i]) { if(in[i] == out[i] + 1) end++; else if(out[i] = in[i] + 1) start++; else { return false; } } if(end > 1 || start > 1) { return false; } } if(start + end > 2) { return false; } return true; } int main() { int T; scanf("%d",&T); while(T--) { read(); if(judge_connect() && judge_deg()) { printf("Ordering is possible.\n"); } else { printf("The door cannot be opened.\n"); } } }