看到收尾相接类似的题目应该想到欧拉路径
有向图中欧拉通路存在条件是:有且仅有一个点出度比入度大 11(起点),有且仅有一个点入度比出度大 11(终点),其余点入度等于出度。
有向图中欧拉回路存在条件是:所有点入度等于出度。
读入字符串的时候进行入度出度的统计,如果是欧拉通路,那就找入度大于出度的点为起点,如果是欧拉回路那就找字典序最小的点。
#include<bits/stdc++.h>
using namespace std;
int n;
int be,en;//开头和结尾
int in[200];
int vis[1001];//点的数量,注意数据范围
vector<string>d;
vector<string>ans;
int flag;
void print()//输出答案
{
for(int i=0; i<n; i++)
{
if(i!=0)
cout<<".";
cout<<ans[i];
}
}
void dfs(int head,int k)
{
if(flag==1)//便于退出dfs
return;
if(k==n)
{
if(head==en)//结尾找到了
{
print();
flag=1;
}
return ;
}
for(int i=0; i<n; i++)//经典的dfs
{
if(d[i][0]==head&&!vis[i])
{
vis[i]=1;
ans.push_back(d[i]);
dfs(d[i][d[i].size()-1],k+1);
ans.pop_back();
vis[i]=0;
}
}
return ;
}
int main()
{
scanf("%d",&n);
memset(in,0,sizeof(in));
for(int i=0; i<n; i++)
{
string t;
cin>>t;
d.push_back(t);
in[t[0]]++;//入度出度计算
in[t[t.size()-1]]--;
}
sort(d.begin(),d.end());//排序
int a,b;
a=0;
b=0;
for(int i='a'; i<='z'; i++)
{
if(in[i]==1)
{
a++;
be=i;//找到起点
}
if(in[i]==-1)
{
b++;
en=i;//找到终点
}
}
memset(vis,0,sizeof(vis));
if((a==1&&b==1)||(a==0&&b==0))//欧拉通路和欧拉回路
{
if(a==1&&b==1)//欧拉通路的情况
{
flag=0;
dfs(be,0);
}
else//欧拉回路的情况
{
flag=0;
en=d[0][0];//开头和结尾一样
dfs(d[0][0],0);
}
if(flag!=1)//注意如果无解,即没找到答案要特殊处理,flag==1代表找到答案
cout<<"***"<<endl;
}
else//不存在欧拉路径
{
cout<<"***"<<endl;
}
return 0;
}