给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
aloha
dog
arachnid
gopher
tiger
rat
可以拼接成:aloha.arachnid.dog.gopher.rat.tiger
2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm
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中用来存放每个字符串的大小Size int 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; else return -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; } else return -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; else b = 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]]); } else printf("***\n"); } }
原文地址:http://blog.csdn.net/y1196645376/article/details/45286509