建模型的思路值得学习
最原始的思路:直接把单词看成一个点,然后和前后可相连的进行连边,但是本题这样做复杂度太大了
不如将单词抽象成一条边,a-z总共26个字符抽象成点,由单词首字母连向单词尾字母
本题就变成了在图上跑欧拉通路
建完图后只要判一判这个图是不是欧拉图就行,1.考虑是否至多有两个点的度数为奇数,2.考虑是否联通
#include<bits/stdc++.h> using namespace std; #define N 100005 int in[100],out[100],mp[50][50]; char s[N]; int vis[N]; void dfs(int u){ vis[u]=1; for(int i=0;i<26;i++) if(mp[u][i] && !vis[i])dfs(i); } int main(){ int n,t;cin>>t; while(t--){ cin>>n; memset(in,0,sizeof in); memset(out,0,sizeof out); memset(mp,0,sizeof mp); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++){ scanf("%s",s); int len=strlen(s); out[s[0]-'a']++; in[s[len-1]-'a']++; mp[s[0]-'a'][s[len-1]-'a']++; } int p=-1,f1=0,f2=0; for(int i=0;i<26;i++){ if(in[i]==out[i])continue; else if(in[i]+1==out[i])f2++,p=i; else if(in[i]==out[i]+1)f1++; else f1=-0x3f3f3f3f; } if(f1<0 || f1>1 || f2>1){ cout<<"The door cannot be opened."<<' '; continue; } //判联通性 if(p>=0)dfs(p);//欧拉通路 else { //欧拉回路 for(int i=0;i<26;i++) if(in[i]){ dfs(i);break; } } int f=0; for(int i=0;i<26;i++) if((in[i] || out[i]) && vis[i]==0)f=1; if(f) cout<<"The door cannot be opened."<<' '; else cout<<"Ordering is possible."<<' '; } }