题意:
给了一堆单词..两个单词能相连当且仅当前一个单词的最后一个字母等于后一个单词的第一个字母..请问是否能将所有的单词连成一条线..如果可以..请输出字典序最小的方案("."不记在字典序比较的范围上..字典序最小是指每一个单词依次比较)
题解:
首先把所有单词读进来..既然要字典序最小.就把所有单词排序...因为我的邻接表是采用前插法..所以从字典序最大的单词到字典序最小的单词依次做边..并且做并查集已经计算各点的度...判断可行..首先要图是联通的..用并查集即可..然后是要保证(只有一个点出度比如度大1..只有一个点入度比出度大1) or (所有点的入度等于其出度)...找路径的时候也是分为这两种情况..分别从不同的入口进入..进行dfs即可...第一种情况已经知道了路径起点..直接从这个点进去..第二种情况实际上是存在欧拉回路了.那么从1号边的起点进入...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 10005
#define MAXM 100005
using namespace std;
struct node
{
int y,id,next;
}line[MAXM];
char ss[25];
string p[1005],ans[1005];
int Lnum,_next[26],d[26],num,father[26],h[1005][2];
bool used[1005];
void addline(int x,int y,int id)
{
line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y,line[Lnum].id=id;
}
int getfather(int x)
{
if (father[x]==x) return x;
return father[x]=getfather(father[x]);
}
bool judge(int &t1,int &t2,int m)
{
int i;
for (i=0;i<26;i++)
if (used[i] && getfather(i)!=m) return false;
for (i=0;i<26;i++)
{
if (!d[i]) continue;
if (d[i]==1)
{
if (t1!=-1) return false;
t1=i;
}
else
if (d[i]==-1)
{
if (t2!=-1) return false;
t2=i;
}else return false;
}
if (t1==-1 && t2!=-1 || t1!=-1 && t2==-1) return false;
return true;
}
void dfs(int x)
{
for (int k=_next[x];k;k=line[k].next)
{
if (used[k]) continue;
used[k]=true;
dfs(line[k].y);
ans[++num]=p[line[k].id];
}
}
int main()
{
int C,cases,n,i,x,y,m;
scanf("%d",&C);
for (cases=1;cases<=C;cases++)
{
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%s",&ss),p[i]=ss;
for (i=0;i<26;i++) father[i]=i;
sort(p+1,p+1+n);
memset(d,0,sizeof(d));
memset(used,false,sizeof(used));
Lnum=0,memset(_next,0,sizeof(_next));
for (i=n;i>=1;i--) //因为我的邻接表是前插法,所以倒着保证字典序
{
x=p[i][0]-'a',y=p[i][p[i].length()-1]-'a';
h[i][0]=x,h[i][1]=y;
d[x]++,d[y]--;
used[x]=used[y]=true;
father[getfather(x)]=getfather(y);
m=getfather(x);
addline(x,y,i);
}
int t1=-1,t2=-1;
if (!judge(t1,t2,m)) printf("***");
else
{
num=0,memset(used,false,sizeof(used));
if (t1!=-1) dfs(t1); //只有欧拉通路
else dfs(h[1][0]); //存在欧拉回路
for (i=num;i>1;i--) printf("%s.",ans[i].c_str());
printf("%s",ans[i].c_str());
}
printf("\n");
}
return 0;
}