Live2d Test Env

HihoCoder1644 : 完美命名的烦恼([Offer收割]编程练习赛37)(有向图的一笔画问题||欧拉路)

描述

程序员常常需要给变量命名、给函数命名、给项目命名、给团队命名…… 好的名字可以大大提高程序员的主观能动性,所以很多程序员在起名时都会陷入纠结和烦恼。

小Hi希望给新的项目起个完美的名字。首先小Hi给出了新项目的N个长度相等(均为L)的关键字,他希望能找到一个完美名字:这个名字的长度恰好为N+L-1,并且其中N个长度为L的子串恰好是给定的N个关键字。  

例如对于关键字cat、ate、tea有完美的名字:catea。  

给定N个长度相等的关键字,请你帮小Hi找到一个完美的名字。

输入

第一行包含一个整数N。  

以下N行每行包含一个长度为L的关键字。  

对于30%的数据,1 ≤ N ≤ 10  

对于100%的数据,1 ≤ N ≤ 50000,1 ≤ L ≤ 10,关键字只包含小写字母。

输出

如果存在完美的名字,你可以输出任意一个。如果不存在,输出NO。

样例输入

3  
ate  
cat  
tea

样例输出

catea

 模型:成语接龙。

以前做过类似的题,有所灵感,知道怎么建图。

  • 如单词abcd,我们加一条有向边abc->bcd,
  • 那么ate,cat,tea,就是有边at->te, ca->at, te->ea。那么一笔画就是ca->at->te-ea,得到catea。

做完的感触。

  • 真的是wa了好久,主要是没有考虑只有一个字母长度的情况(毕竟代码里有‘L-2’这个东西)
  •  注意‘NO’的情况,如果不能连通;如果连通了但是不满足欧拉路的条件(无奇点,或一个起点一个终点)
  • 逆序输出。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
const int maxn=200010;
map<string,int>mp;
map<int,string>name;
char c[20];string s1,s2;
int Laxt[maxn],Next[maxn],To[maxn],cnt,tot,num;//边,点,路 
int id[maxn],od[maxn],used[maxn],path[maxn]; 
int a[maxn],b[maxn];//起点;
void add(int u,int v)
{
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt;
    To[cnt]=v;
}
void dfs(int u)                  //Fluery算法 
{
    for(int i=Laxt[u];i;i=Next[i]){
        if(!used[i]){
            used[i]=1;
            dfs(To[i]);
        }    
    }
    path[++num]=u;
}
int main()
{
    int n,i,j,L;bool Flag=false;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%s",c);
        L=strlen(c);
        if(L==1){
            cout<<c[0];
            Flag=true;
        }
        s1=s2="";
        for(j=0;j<L-1;j++)s1+=c[j];
        for(j=1;j<L;j++) s2+=c[j];
        if(mp.find(s1)==mp.end()) mp[s1]=++tot,name[tot]=s1;
        if(mp.find(s2)==mp.end()) mp[s2]=++tot,name[tot]=s2;
        a[i]=mp[s1];b[i]=mp[s2];
        od[a[i]]++;id[b[i]]++;
        add(a[i],b[i]); 
    }
    if(Flag) { cout<<endl;return 0;}                         //只有单个字母,坑了我好久 
    int S=1,c1=0,c2=0;
    for(i=1;i<=tot;i++){
        if(od[i]-id[i]==1) c1++,S=i;
        else if(od[i]-id[i]==-1) c2++;
        else if(od[i]-id[i]!=0) c1=3;
    }
    if(!((c1==0&&c2==0)||(c1==1&&c2==1)))  cout<<"NO"<<endl;//不满足欧拉路 
    else{
          dfs(S); 
          if(num!=n+1) cout<<"NO"<<endl;                    //不连通(也可以用并查集做) 
          else {
             cout<<name[S];
             for(i=num-1;i>=1;i--) cout<<name[path[i]][L-2];
          }
    }
    return 0;
}

 

posted @ 2017-12-28 09:30  nimphy  阅读(802)  评论(0编辑  收藏  举报