2018.11.07-1117-无序字母对 character

题目描述:

给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

输入:

第一行输入一个正整数n。 
以下n行每行两个字母,表示这两个字母需要相邻。

输出:

输出满足要求的字符串。 
如果没有满足要求的字符串,请输出“No Solution”。 
如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

算法标签:欧拉路??我觉得我是贪心爆搜啊??

写完才知道欧拉路是个什么鬼

思路:

有两种情况,第一种存在两个度数为奇数的点,此时在两个点内挑一个字典序小的暴力跑,每次优先跑字典序小的,跑到底不合法return,换路跑,暴力的很。

第二种情况所有点度数为偶数,此时要合法说明是一个欧拉回路,所以选一个字典序最小的跑。

以下代码:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=55,M=3005;
int n,in[N],que[55],tot,fir,kk,link[N][N],res[M],tt;
char s[10];
il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
il int getnum(char t){
    if(t>='A'&&t<='Z')return t-'A'+1;return t-'a'+27;
}
il char getch(char t){
    if(t<=26)return t+'A'-1;return t+'a'-27;
}
il bool work(int x,int tt){
    res[tt]=x;if(tt==n+1)return 1;
    for(int i=1;i<=52;i++){
        if(link[x][i]){
            link[x][i]=0;link[i][x]=0;if(work(i,tt+1))return 1;
            link[x][i]=1;link[i][x]=1;
        }
    }
    return 0;
}
int main()
{
    n=read();for(int i=1;i<=n;i++){
        scanf(" %s",&s);int x=getnum(s[0]),y=getnum(s[1]);
        link[x][y]=link[y][x]=1;in[x]++;in[y]++;
    }
    for(int i=1;i<=52;i++){
        if(in[i]&1)que[++tot]=i;if(!fir&&in[i])fir=i;
    }
    if(tot>2){puts("No Solution");return 0;}
    if(tot==2){if(que[1]<que[2])fir=que[1];else fir=que[2];}
    int x=fir;
    if(!work(fir,1)){puts("No Solution");return 0;}
    for(int i=1;i<=n+1;i++)printf("%c",getch(res[i]));
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/Jessie-/p/9925897.html