内容
/*
* 次小生成树
* 求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
* 求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
* 点的编号从0开始
*/
上海大学 ACM 模板 by kuangbin
94 / 173 ACM 模板 kuangbin
int pre[MAXN],id[MAXN],visit[MAXN],in[MAXN];
int zhuliu(int root,int n,int m,Edge edge[])
{
int res = 0,u,v;
while(1)
{
for(int i = 0;i < n;i++)
in[i] = INF;
for(int i = 0;i < m;i++)
if(edge[i].u != edge[i].v && edge[i].cost < in[edge[i].v])
{
pre[edge[i].v] = edge[i].u;
in[edge[i].v] = edge[i].cost;
}
for(int i = 0;i < n;i++)
if(i != root && in[i] == INF)
return -1;//不存在最小树形图
int tn = 0;
memset(id,-1,sizeof(id));
memset(visit,-1,sizeof(visit));
in[root] = 0;
for(int i = 0;i < n;i++)
{
res += in[i];
v = i;
while( visit[v] != i && id[v] == -1 && v != root)
{
visit[v] = i;
v = pre[v];
}
if( v != root && id[v] == -1 )
{
for(int u = pre[v]; u != v ;u = pre[u])
id[u] = tn; 上海大学 ACM 模板 by kuangbin
94 / 173 ACM 模板 kuangbin
id[v] = tn++;
}
}
if(tn == 0)break;//没有有向环
for(int i = 0;i < n;i++)
if(id[i] == -1)
id[i] = tn++;
for(int i = 0;i < m;)
{
v = edge[i].v;
edge[i].u = id[edge[i].u];
edge[i].v = id[edge[i].v];
if(edge[i].u != edge[i].v)
edge[i++].cost -= in[v];
else
swap(edge[i],edge[--m]);
}
n = tn;
root = id[root];
}
return res;
}
</pre><pre name="code" class="cpp">
void addedge(int u,int v,int w)
{
edges[ecnt++]=Edge(u,v,w);
}
int zhu_liu()
{
int weight=0,i,j,u,v,root=0;
while (1)
{
for(i=0;i<N;i++){
dist[i]=INF;
num[i]=-1;
s[i]=-1;
}
dist[root]=0;
pre[root]=-1;
int cnt=0;
for (i=0;i<ecnt;i++){
Edge e=edges[i];
if (e.u==e.v) continue;
if (dist[e.v]>e.w){
dist[e.v]=e.w;
pre[e.v]=e.u;
}
}
for (i=0;i<N;i++){
if (dist[i]==INF)
return -1;
weight+=dist[i];
u=i;
while (pre[u]!=-1&&s[u]!=i&&num[u]==-1) {
s[u]=i;
u=pre[u];
}
if (s[u]==i){
while (num[u]==-1){
num[u]=cnt;
u=pre[u];
}
cnt++;
}
}
if (cnt==0) return weight;
for (i=0;i<N;i++){
if (num[i]==-1){
num[i]=cnt++;
}
}
for (i=0;i<ecnt;i++){
Edge &e=edges[i];
e.w-=dist[e.v];
e.u=num[e.u];
e.v=num[e.v];
}
root=num[root];
N=cnt;
}
return weight;
}
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
#define MAXM 10010
#define MAX 40
struct Edge
{
int v,num;
Edge(){}
Edge(int x,int y)
{
this->v=x;
this->num=y;
}
};
string s[MAXM];
int n,in[MAX],out[MAX];
int mark[MAXM],E[MAXM],U[MAXM];
vector<Edge>G[MAX];
int parent[MAX],vis[MAX];
bool cmp(string a,string b)
{
return a<b;
}
int find(int x)
{
if (parent[x]>=0)
{
return parent[x]=find(parent[x]);
}
return x;
}
int check()
{
int i,cnt=0,cntx=0,cnty=0,start=-1;;
for (i=0;i<26;i++)
{
if (vis[i])
{
if (start==-1)
start=i;
if (parent[i]==-1)
{
// cout<<"cnt"<<endl;
cnt++;
if (cnt>1)
return -1;
}
if (in[i]-out[i]==-1)
{
start=i;
cntx++;
}
else if (in[i]-out[i]==1)
{
cnty++;
}
else if (abs(in[i]-out[i])>1)
{
// cout<<"xxxx"<<endl;
return -1;
}
}
if (cntx>1||cnty>1)
{
return -1;
}
}
return start;
}
int main()
{
int T;
// ios::sync_with_stdio(false);
// freopen()
cin>>T;
while (T--)
{
cin>>n;
int i,j,u,v,flag,L;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(mark,0,sizeof(mark));
memset(parent,-1,sizeof(parent));
memset(vis,0,sizeof(vis));
for (i=0;i<26;i++)
{
G[i].clear();
}
for (i=0;i<n;i++)
{
cin>>s[i];
}
sort(s,s+n,cmp);
for (i=0;i<n;i++)
{
// cout<<s[i]<<endl;
u=s[i][0]-'a';
L=s[i].size();
v=s[i][L-1]-'a';
U[i]=v;
G[u].push_back(Edge(v,i));
in[v]++,out[u]++;
vis[u]=vis[v]=1;
u=find(u);
v=find(v);
if (u!=v)
{
parent[u]=v;
}
}
flag=check();
if (flag<0)
{
cout<<"***"<<endl;
}
else
{
int cnt=0;
stack<int>S;
for (i=0;i<G[flag].size();i++)
{
Edge e=G[flag][i];
if (!mark[e.num])
{
mark[e.num]=1;
S.push(e.num);
break;
}
}
while (!S.empty())
{
flag=0;
int temp=S.top();
u=U[temp];
for (i=0;i<G[u].size();i++)
{
Edge e=G[u][i];
if (!mark[e.num])
{
mark[e.num]=1;
S.push(e.num);
flag=1;
break;
}
}
if (!flag)
{
// cout<<S.top()<<endl;
E[cnt++]=S.top();
S.pop();
}
}
for (i=cnt-1;i>=0;i--)
{
cout<<s[E[i]];
if (i!=0)
{
cout<<".";
}
}
cout<<endl;
}
}
return 0;
}