洛谷 P1341 无序字母对 Label:欧拉路 一笔画

题目描述

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

输入输出格式

输入格式:

 

第一行输入一个正整数n。

以下n行每行两个字母,表示这两个字母需要相邻。

 

输出格式:

 

输出满足要求的字符串。

如果没有满足要求的字符串,请输出“No Solution”。

如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

 

输入输出样例

输入样例#1:
4
aZ
tZ
Xt
aX
输出样例#1:
XaZtX
 

说明

【数据规模与约定】

不同的无序字母对个数有限,n的规模可以通过计算得到。

代码

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define INF 0x3f3f3f3f
 6 using namespace std;
 7 int tot,p,N,x,y,k=INF;
 8 int a[10005],c[10005],du[10005],b[105][105];
 9 char str[3];
10 
11 void dfs(int u){
12     for(int i=0;i<58;i++){ //A到z之间还有一些字符,总共58个~   
13         if(b[u][i]){
14             b[u][i]=b[i][u]=0;
15             dfs(i);
16 //            break;
17         }
18     }
19     c[++tot]=u;
20 }
21 
22 
23 int main(){
24 //    freopen("01.in","r",stdin);
25     scanf("%d",&N);
26     for(int i=1;i<=N;i++){
27         scanf("%s",str);
28         x=str[0]-'A',y=str[1]-'A';//字符串从0开始读入
29         k=min(k,min(x,y));
30         b[x][y]=b[y][x]=1;
31         ++du[x],++du[y];
32     }
33     for(int i=0;i<58;i++){
34         if(du[i]&1){
35             a[++p]=i;
36         }
37     }
38     
39     if(p==0) dfs(k);
40     else if(p==2) dfs(a[1]);
41     else{
42         puts("No Solution");
43         return 0;
44     }
45     
46     for(int i=tot;i>=1;i--){
47         printf("%c",c[i]+'A');
48     }
49     
50     return 0;
51 }

照例转载题解:

把两个字母拆成两个顶点 然后构造一个无向图 ,这样根据欧拉回路 当一个图中每个点的度数都是偶数时 纯在欧拉环 而只有2个奇数度数时,存在欧拉路径 因此先验证一下然后dfs 这里为了储存答案我用了双端队列,当然也可以不用 偷点懒,至于最小字典序的话 拍一下序就好了 而如果你用 vector的话 直接从小到大排序(我就是这么做的),而如果你用链表的号 需要首字母从小到大 第二个字母从大到小

 

我再说两句:

按照欧拉路的性质,若有度奇数点,只能从奇数点走,

本题中若没有则按照题意以Line39的处理方式从ASCII最小序走

 

特别注意!!!

Line16不可写!!!

这样不写处理的话字符串会以一种神奇的方式连接起来!!!,想想看为什么~

posted @ 2016-09-16 13:23  Radiumlrb  阅读(400)  评论(0编辑  收藏  举报