P1341 无序字母对 - 欧拉(回)路

传送门

将字母看做点,将相邻字母见看做有连一条无向边,最终判断能否形成一条由n+1个点构成的路径,即是否存在一条欧拉路或欧拉回路。

由于要字典序最小,所以按字典序从小到大遍历,找最小的字母为起点,每次找最小的字母作为下一个点。

由于欧拉(回)路是倒序存储的,所以输出答案时需要倒着输出。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2000,M=50000+100;
bool e[100][100];
int deg[100];
int c(char a){
    if(a>='a'&&a<='z') return a-'a'+27;
    return a-'A'+1;
}
char pout(int a){
    if(a>=1&&a<=26) printf("%c",a+'A'-1);
    else printf("%c",a+'a'-27);
}
int ans[100000],t;
int root=(1<<30);
void dfs(int u){
    for(int i=1;i<=52;i++){
        if(e[u][i]||e[i][u]){
            e[u][i]=e[i][u]=0;
            dfs(i);
        }
    }
    ans[++t]=u;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        char u,v;
        cin>>u>>v;
        e[c(u)][c(v)]=e[c(v)][c(u)]=1;
        deg[c(v)]++,deg[c(u)]++;
    }
    int cnt=0;
    for(int i=1;i<=52;i++) if(deg[i]%2) {
        cnt++;root=min(root,i);
    }
    if(cnt!=2&&cnt) {
        printf("No Solution\n");return 0;
    }
    if(!cnt) {
        for(int i=1;i<=52;i++)
            if(deg[i]) {
                root=i;break;
            }
    }
    dfs(root);
    for(int i=t;i>=1;i--){
        pout(ans[i]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/9124313.html