NYOJ-99: Word Stitching

Word Stitching

Source: NYOJ

Tags: Graph Theory, Euler Tu, Euler Path

Reference material:

Euletu: https://baike.baidu.com/item/Euletta

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;
}

Posted by covert215 on Mon, 29 Apr 2019 05:40:36 -0700