给出n个单词,问能否将这n个单词连成串,使得每个单词最后一个字母和下个单词第一个字母相同。
首先对单词预处理,变为从首字母到最后一个字母的有向边,将单词集合变为有向图。
然后统计每个点的入度和出度,至多有两个点出度和入度不相等,且一点出度比入度大1,另一点入度比出度大1。
再判断连通性,所有出现过的单词必须连通。
满足以上条件即能连成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| #include<iostream> #include<cstring> #include<string> using namespace std; const int maxn=30; int n,inp[maxn],outp[maxn]; bool k,vis[maxn],g[maxn][maxn]; void dfs(int u){ vis[u]=false; for (int v=0;v<26;v++) if (vis[v]&&g[u][v]) dfs(v); } int main(){ int t; cin>>t; while(t--){ cin>>n; memset(inp,0,sizeof(inp)); memset(outp,0,sizeof(outp)); memset(vis,0,sizeof(vis)); memset(g,0,sizeof(g)); k=true; string s; for(int i=0;i<n;i++){ cin>>s; inp[s[0]-'a']++; outp[s[s.size()-1]-'a']++; vis[s[0]-'a']=vis[s[s.size()-1]-'a']=true; g[s[0]-'a'][s[s.size()-1]-'a']=true; } int cnt1=0,cnt2=0,sta=s[0]-'a'; for(int i=0;i<26;i++){ if(!k) break; inp[i]-=outp[i]; if(inp[i]!=0){ if(inp[i]==1){ cnt1++; sta=i; } else if(inp[i]==-1) cnt2++; else k=false; } } if(cnt1>1||cnt2>1) k=false; dfs(sta); for(int i=0;i<26;i++){ if(!k) break; if(vis[i]) k=false; } if(k) cout<<"Ordering is possible."<<endl; else cout<<"The door cannot be opened."<<endl; } return 0; }
|
** 本文迁移自我的CSDN博客,格式可能有所偏差。 **