给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
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 ***
开始打算直接用dfs搜一下,仔细想想肯定会超时啊。参照网上思路,先根据欧拉通路,欧拉回路的定义将不满足条件的情况直接排除,大大缩小了时间复杂度,然后给字符串排序,从找到的欧拉回路或欧拉通路的起点开始深搜路径,(因为找欧拉通路,欧拉回路是从 a ~ z 字典序找的,所以保证了起点的字典序最小,同理在dfs的同时也是 a~z 去找) 。
注意出度是 单词的首字母,因为其他单词的尾字母要连接该单词的首字母。
//无向图
欧拉回路:联通图,无奇度顶点。
欧拉通路:联通图,恰好有两个奇度顶点。
//有向图
欧拉回路 :联通图,所有顶点入度等于出度
欧拉通路: 欧拉回路,或者只有一个点的入度比出度大一,只有一个点的入度比出度小一。
只要抽象出欧拉回路通路的模型来,这题就简单编程了。
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <cstring> #include <algorithm> using namespace std; int n; int l[1010]; int in[1010],out[1010];bool vis[1010];int route[1010]; struct node{ char s[40]; int l,r; }no[1010]; int dfs(int x,int cnt){ if(cnt == n){ return 1; } for(int i=0;i<n;i++){ if(vis[i] || no[i].l < x) continue; else if(no[i].l > x) return false; // 因为单词已经有序了,所以只要下一个节点的首字母比 x大就不可能找到相同的了 route[cnt] = i; vis[i] = 1; if(dfs(no[i].r,cnt+1)) return 1; vis[i] = 0; } return 0; } int euler(){ int start = -1,end = -1; for(int i=0;i<26;i++){ if(out[i] != in[i]){ if(out[i] - in[i] == 1 && start == -1)//找第一个入度 比 出度 的 start = i; else if(out[i] - in[i] == -1 && end == -1) end = i; else // 入度出度不等 ,且不满足上述条件,则不存在欧拉通路,或者回路 return -1; } } if(start >-1 && end > -1) return start; if(start == -1 && end == -1){ //存在欧拉回路 for(int i=0;i<26;i++) if(out[i] != 0) return i; //找到第一个出度不为0的,字典序最小了 } return -1; } bool cmp(node a,node b){ return strcmp(a.s,b.s)<0; } int main() { int t; scanf("%d",&t); while(t--){ memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s",no[i].s); int len = strlen(no[i].s); no[i].l = no[i].s[0] - 'a'; no[i].r = no[i].s[len-1] - 'a'; out[no[i].l]++; in[no[i].r]++; //首字母是出度 ,画图测试个样例就知道了 } int start = euler(); if(start == -1){ printf("***\n"); continue; } sort(no,no+n,cmp); if(dfs(start,0)){ for(int i=0;i<n-1;i++){ printf("%s.",no[route[i]].s); } printf("%s\n",no[route[n-1]].s); } else printf("***\n"); } return 0; }