標籤:c語言 dfs 歐拉
單詞拼接
-
描述
-
給你一些單詞,請你判斷能否把它們首尾串起來串成一串。
前一個單詞的結尾應該與下一個單詞的道字母相同。
如
aloha
dog
arachnid
gopher
tiger
rat
可以拼接成:aloha.arachnid.dog.gopher.rat.tiger
-
輸入
-
第一行是一個整數N(0<N<20),表示測試資料的組數
每組測試資料的第一行是一個整數M,表示該組測試資料中有M(2<M<1000)個互不相同的單詞,隨後的M行,每行是一個長度不超過30的單詞,單詞全部由小寫字母組成。
-
輸出
-
如果存在拼接方案,請輸出所有拼接方案中字典序最小的方案。(兩個單詞之間輸出一個英文句號".")
如果不存在拼接方案,則輸出
***
-
範例輸入
-
26alohaarachniddoggopherrattiger3oakmapleelm
-
範例輸出
-
aloha.arachnid.dog.gopher.rat.tiger***
-
有向圖G 為歐拉迴路:
若且唯若G 的基圖連通,且所有頂點的入度等於出度。
有向圖G 為歐拉路:
若且唯若G 的基圖連通,且只存在一個頂點u 的入度比出度大1、
只存在一個頂點v 的入度比出度小1,其它所有頂點的入度等於出度。
分析:此題應把單詞的首字母和尾字母抽離出來,首字母出度+1,尾字母入度+1,這樣就可以根據每個字母的出度和入度判斷起點和終點。特別的,如果是歐拉迴路的話,任何一點就可以作為起點,這時候我們按照題意選擇字典順序靠前的.
#include<stdio.h>#include<string.h>#include<stdlib.h>char str[1000][31];//儲存字串bool used[1000]; //dfs的時候判斷單詞是否用過int In[26]; //入度int Out[26]; //出度int s[1000];//在Judge中用來存放每個字串的大小Sizeint stack[1000]; //dfs儲存結果int n;int compare(const void *a, const void *b)//字串排序 {char *p1 = (char *)a;char *p2 = (char *)b;return strcmp(p1, p2);}int Judge()//檢測歐拉 {int i;int last = -1;int first = -1;for(i = 0; i < 26; ++i){if(In[i] != Out[i]){//Out為在串首出現的次數,In為串尾出現的次數if(Out[i] - In[i] == 1 && first == -1) first = i;else if(Out[i] - In[i] == -1 && last == -1)last = i;elsereturn -1; }}if(first > -1 && last > -1) //歐拉通路return first;else if(first == -1 && last == -1) //歐拉迴路{for(i = 0; i < 26; ++i)if(In[i] != 0)return i;}elsereturn -1;}bool DFS(char first, int Index)//有可能有多個連通地區{if(Index == n) //加了這個判斷.就不用並查集檢測了return true;int i;int b,e,m;b = 0;e = n - 1;while(b <= e)//二分法尋找這個首字元,排序好的,肯定快啊。速度絕對比別人快2倍{m = (b + e)/2;if(str[m][0] == first)break;else if(str[m][0] > first)e = m - 1;elseb = m + 1;}if(b > e)return false;//找到這個字元第一次出現的字串while(str[m][0] == first && m >= 0) --m;for(i = m + 1; str[i][0] == first; ++i){if(!used[i]){stack[Index] = i;used[i] = true;if(DFS(str[i][s[i] - 1], Index + 1))return true;used[i] = false;}}return false;}int main(){int t;int i,first;scanf("%d", &t);while(t--){scanf("%d", &n);for(i = 0; i < n; ++i)scanf("%s", str[i]);memset(used, 0, sizeof(used));memset(In, 0, sizeof(In));memset(Out, 0, sizeof(Out));qsort(str, n, 31 * sizeof(char), compare); //字串排序for(i = 0; i < n; ++i) //抽離首尾字母統計出入度{s[i] = strlen(str[i]);++Out[str[i][0] - 'a'];++In[str[i][s[i] - 1] - 'a'];}first = Judge(); //判斷起點if(first != -1 && DFS(first + 'a', 0)){for(i = 0; i < n - 1; ++i)printf("%s.", str[stack[i]]);printf("%s\n", str[stack[n - 1]]);}elseprintf("***\n");}}
C語言DFS(7)___單詞拼接(NYoj 99)