词链

题目链接:https://www.luogu.com.cn/problem/P1127

题意:

给定n个单词,后面单词的第一个字母与前面单词的最后一个字母相同,输出字典序最小的排列

思路:

经典欧拉路径问题

单词作为边,该单词的第一个字母和最后一个字母作为节点建图

1.建立并查集,判断图的连通性

2.观察节点的入度和出度,判断是否满足欧拉路径条件

  1. Hierholzer 算法递归遍历边,将答案压栈
int n;
struct edge{
    int v;string word;
};
vector<edge>e[26];
int ieg[maxn];
int oeg[maxn];
int f[maxn];
int find(int x){
    if(f[x]!=x)f[x]=find(f[x]);return f[x];
}
void merge(int x,int y){
    if(find(x)!=find(y)){
        f[find(x)]=find(y);
    }
}
bool cmp(edge a,edge b){
    return a.word<b.word;
}
stack<string>stk;
int now[maxn];
void dfs(int u){
    for(int i=now[u];i<e[u].size();i=now[u]){
        now[u]=i+1;
        dfs(e[u][i].v);
        stk.push(e[u][i].word);
    }
}
void solve(){
    cin>>n;
    rep(i,0,26)f[i]=i;
    vector<int>k;
    int st=25,ed=0;
    rep(i,1,n){
        string s;cin>>s;
        int a=s[0]-'a';
        int b=s[s.size()-1]-'a';
        st=min(st,a);
        ed=max(ed,b);
        merge(a,b);
        k.pb(a);k.pb(b);
        e[a].pb((edge){b,s});
        oeg[a]++;
        ieg[b]++;
    }
    int fa=find(k[0]);
    for(int i=0;i<k.size();i++){
        if(fa!=find(k[i])){
            cout<<"***"<<endl;return;
        }
    }

    int cnt=0;
    for(int i=0;i<26;i++){
        if(oeg[i]!=ieg[i]){
            cnt++;
            if(abs(oeg[i]-ieg[i])>1){
                cout<<"***"<<endl;return;
            }
            if(oeg[i]-ieg[i]==1){
                st=i;
            }
            else if(ieg[i]-oeg[i]==1){
                ed=i;
            }
        }    
    }

    if(cnt>2){
        cout<<"***"<<endl;return;
    }

    for(int i=0;i<26;i++){
        sort(e[i].begin(),e[i].end(),cmp);
    }

    dfs(st);

    while(stk.size()){
        cout<<stk.top();
        stk.pop();
        if(stk.size())cout<<'.';
    }
}
posted @ 2025-04-22 12:48  Marinaco  阅读(22)  评论(0)    收藏  举报
//雪花飘落效果