这道题看了题解觉得挺水的,主要是自己建图建得挫。。。不过通过这道题也算学习了建图的一些技巧以及字符串的字典序排序。
i一下为转载别人加上我自己的一些小改动:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
struct Edge
{
int to,next;
int index;
bool flag;
}edge[2010];
int head[30],tot;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int index)
{
edge[tot].to = v;///记录边的终点
edge[tot].next = head[u];///记录之前的tot相当于
edge[tot].index = index;///记录当前的下标
edge[tot].flag = false;
head[u] = tot++;///记录边出现的顺序
}
int cmp(const void * a,const void *b) //qsort库要求参数const
{
return strcmp((char *)a,(char *)b) ; ///字典序从小到大
//return strcmp((char *)b,(char *)a) ; ///字典序从大到小
}
char str[1010][30];
int in[30],out[30];
int cnt;
int ans[1010];
void dfs(int u)
{
for(int i = head[u] ;i != -1;i = edge[i].next)
if(!edge[i].flag)///未访问过
{
edge[i].flag = true;
dfs(edge[i].to);///从终点出发
ans[cnt++] = edge[i].index;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = 0;i < n;i++)
cin>>str[i];
qsort(str,n,sizeof(str[0]),cmp);///要输出字典序最小的解,先按照字典序排序
init();
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
int start = 100;
for(int i = n-1;i >= 0;i--)///字典序大的先加入
{
int len=strlen(str[i]);
int u = str[i][0] - 'a';
int v = str[i][len - 1] - 'a';
addedge(u,v,i);
out[u]++;
in[v]++;
if(u < start)start = u;
if(v < start)start = v;///找最小的做起点
}
int cc1 = 0, cc2 = 0;
for(int i = 0;i < 26;i++)
{
if(out[i] - in[i] == 1)
{
cc1++;
start = i;///如果有一个出度比入度大1的点,就从这个点出发,否则从最小的点出发
}
else if(out[i] - in[i] == -1)
cc2++;
else if(out[i] - in[i] != 0)
cc1 = 3;
}
if(! ( (cc1 == 0 && cc2 == 0) || (cc1 == 1 && cc2 == 1) ))///欧拉回路和欧拉道路都能实现这个问题
{
printf("***\n");
continue;
}
cnt = 0;
dfs(start);
if(cnt != n)///判断是否连通
{
printf("***\n");
continue;
}
for(int i = cnt-1; i >= 0;i--)
{
cout<<str[ans[i]];
if(i > 0)printf(".");
else printf("\n");
}
}
return 0;
}
以及自己MLE的代码(警醒笨笨的自己):
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
set<int> se;
const int maxn=1000+5;
int fa[maxn],ranks[maxn],cnt,t1,t2,record,cases,num,in[maxn],out[maxn],visit[maxn],crt,t;
char str[maxn][30],str1[maxn][30],ans[maxn][30];
int cmp(const void * a,const void *b) //qsort库要求参数const
{
return strcmp((char *)a,(char *)b) ; ///字典序从小到大
//return strcmp((char *)b,(char *)a) ; ///字典序从大到小
}
struct node{
char s[3][25];
int k;
int in;
int out;
node()
{
k=0;
memset(s,0,sizeof(s));
}
}G[maxn][maxn];
void init ()
{
for(int i=0;i<26;i++)
fa[i]=i,ranks[i]=0;
}
int finds(int x)
{
return fa[x]==x?x:fa[x]=finds(fa[x]);
}
void unions(int a,int b)
{
a=finds(a);
b=finds(b);
if(a==b)
return;
if(ranks[a]>ranks[b])
fa[b]=a;
else
{
fa[a]=b;
if(ranks[a]==ranks[b])
++ranks[b];//cout<<1<<endl;
}
}
bool liantong()
{
for(int i=0;i<crt;i++)
for(int j=0;j<i;j++)
if(finds(visit[i])!=finds(visit[j]))
return false;
return true;
}
bool judge2()
{
if(liantong())
{ int i;
for(i=0;i<crt;i++)
if(in[visit[i]]!=out[visit[i]])
{
break;
}
//if(cnt==0||cnt==2)
//printf("1\n");
if(i==crt)
return true;
else
return false;
}
}
bool judge()
{
if(liantong())
{ //cout<<1<<endl;
for(int i=0;i<crt;i++)
if(in[visit[i]]!=out[visit[i]])
{
cnt++;//cout<<"cnt:"<<cnt<<"in:"<<in[visit[i]]<<"out:"<<out[visit[i]]<<"vis:"<<visit[i]<<"i:"<<i<<endl;
if(in[visit[i]]>out[visit[i]])
t1=in[visit[i]]-out[visit[i]];
else if(out[visit[i]]>in[visit[i]])
t2=out[visit[i]]-in[visit[i]];
}
if(cnt==2&&t1==1&&t2==1)
return true;
else return false;
}
return false;
}
void euler(int u)
{
for(int v=0;v<26;v++)
if(G[u][v].k)
{
int temp=G[u][v].k--;
//cout<<"v:"<<v<<endl;
//vis[u][v]=1;
euler(v);//cout<<1<<endl;
strcpy(ans[record++],G[u][v].s[temp]);
}
}
int main()
{
scanf("%d",&cases);
while(cases--)
{
t=0;
t1=t2=0;
record=1;
cnt=0;
crt=0;
se.clear();
//memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
//memset(G,0,sizeof(G));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(str,0,sizeof(str));
memset(str1,0,sizeof(str1));
//memset(ranks,0,sizeof(0));
memset(visit,0,sizeof(visit));
scanf("%d",&num);
for(int i=0;i<num;i++)
{
scanf("%s",str[i]);
}
init();
qsort(str,num,sizeof(str[0]),cmp);
for(int i=num-1;i>=0;i--)
{
int u,v;
int len=strlen(str[i]);
u=str[i][0]-'a';
v=str[i][len-1]-'a';
se.insert(u);
se.insert(v);
int temp=G[u][v].k++;
//cout<<"u:"<<str[i][0]<<"v:"<<str[i][len-1]<<endl;
if(!G[u][v].s[temp])
strcpy(G[u][v].s[temp],str[i]);
else
strcpy(G[u][v].s[++temp],str[i]);
unions(u,v);
++in[v];
out[u]++;
//cout<<"inv:"<<in[v]<<"v:"<<v<<"outu:"<<out[u]<<"u"<<u<<endl;
}
set<int>::iterator it;
for(it=se.begin();it!=se.end();it++)
{visit[crt++]=*it;/*cout<<"it:"<<*it<<endl;*/}
if(judge2())
{
for(int i=0;i<crt;i++)
//if(out[visit[i]]-in[visit[i]]==1)
euler(visit[i]);
for(int i=record-1;i>=1;i--)
printf("%s%c",ans[i],i==1?'\n':'.');
//qsort(ans,record,sizeof(ans[0]),cmp);
}
else if(judge())
{
for(int i=0;i<crt;i++)
if(out[visit[i]]-in[visit[i]]==1)
euler(visit[i]);
for(int i=record-1;i>=1;i--)
printf("%s%c",ans[i],i==1?'\n':'.');
}
else
printf("***");
}
return 0;
}