Word Stitching
Source: NYOJ
Tags: Graph Theory, Euler Tu, Euler Path
Reference material:
Similar topics:
subject
Give you some words and decide if you can string them together.
The end of the previous word should be the same as the letter of the next word.
as
aloha
dog
arachnid
gopher
tiger
rat
Can be stitched into: aloha.arachnid.dog.gopher.rat.tiger
input
The first row is an integer N (0<N<20), which represents the number of groups of test data
The first line of each set of test data is an integer M, which indicates that there are M (2<M<1000) distinct words in the set of test data, followed by M lines, each of which is a word no longer than 30 in length, consisting of all lowercase letters.
output
If stitching schemes exist, output the scheme with the smallest dictionary order among all stitching schemes.(Output an English period'. 'between two words)
If no stitching scheme exists, the output
sample input
2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm
sample output
aloha.arachnid.dog.gopher.rat.tiger
Solving problems
Think of these words as edges, with the first letter as the starting point and the last letter as the ending point.A directed connected graph consisting of all edges fits the theme.Note that it is necessary to first determine if the Euler circuit can be constituted, otherwise the operation will exceed the limit.
Reference Code
#include<cstdio> #include<cstring> #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; struct Word{ string str; bool vis; Word(string str):str(str),vis(false){} bool operator < (const Word &rhs) const{ return str<rhs.str; } }; vector<Word> word[26]; vector<string> dragon; //Generated stitching int set[26]; //And look up sets to determine connectivity int in[26], out[26]; //Incoming and Outgoing int N, M; //And Search Sets int find(int v){ while(v!=set[v]) v=set[v]; return v; } void join(int u, int v){ int ra=find(u); int rb=find(v); if(ra==rb) return; set[ra]=rb; } //Depth first search bool dfs(int s){ if(dragon.size()==M) return true; for(int i=0;i<word[s].size();i++){ if(word[s][i].vis==false){ string str=word[s][i].str; dragon.push_back(str); word[s][i].vis=true; if(dfs(str[str.size()-1]-'a')==true) return true; word[s][i].vis=false; dragon.erase(dragon.end()-1); } } return false; } int main(){ scanf("%d",&N); while(N--){ memset(set, 0, sizeof(set)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); for(int i=0;i<26;i++) word[i].clear(); dragon.clear(); string str; scanf("%d",&M); for(int i=0;i<M;i++){ cin>>str; word[str[0]-'a'].push_back(Word(str)); set[str[0]-'a']=str[0]-'a'; in[str[str.size()-1]-'a']++; //Initiation out[str[0]-'a']++; //Outbound } //sort for(int i=0;i<26;i++){ sort(word[i].begin(), word[i].end()); } bool euler=true; //Judging Euletta //Judging Connectivity for(int i=0;i<26;i++){ for(int j=0;j<word[i].size();j++){ str=word[i][j].str; join(str[0]-'a', str[str.size()-1]-'a'); } } int root=-1; for(int i=0;i<26;i++){ for(int j=0;j<word[i].size();j++){ str=word[i][j].str; if(root==-1) root=find(str[0]-'a'); if(find(str[0]-'a')!=root){ euler=false; break; } } if(euler==false) break; } if(euler==false){ cout<<"***"<<endl; continue; } //Calculating degrees int bg=-1; //Bg's degree of entry+1==bg's degree of exit.BG as starting point int ed=-1; //Ed's degree of entry==ed's degree of exit+1 for(int i=0;i<26;i++){ if(in[i]!=out[i]){ if(in[i]+1==out[i]){ if(bg!=-1){ euler=false; break; } bg=i; } else if(in[i]==out[i]+1){ if(ed!=-1){ euler=false; break; } ed=i; } else{ euler=false; break; } } } if(euler==false){ cout<<"***"<<endl; continue; } //If no starting point is found, start with the first not empty if(bg==-1){ for(int i=0;i<26;i++){ if(in[i]!=0){ dfs(i); break; } } } //Find the starting point, then start from the starting point else dfs(bg); for(int i=0;i<dragon.size();i++){ if(i!=0) cout<<"."; cout<<dragon[i]; } cout<<endl; } return 0; }