欧拉回路 无序字母队

欧拉路径

 

 

 

 

 

 

 

 

 

 

 

 

 

 

题目描述

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

输入格式

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

第二行到第 (n+1)(n+1)(n+1) 行每行两个字母,表示这两个字母需要相邻。

输出格式

输出满足要求的字符串。

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

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

输入输出样例

输入 #1
4
aZ
tZ
Xt
aX
输出 #1
XaZtX
 

说明/提示

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

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n;
 5 int vhash[1100][1100];
 6 int tot=0;
 7 int vis[11000];
 8 int gin[11000];
 9 
10 void readp(){
11     cin>>n;
12     for(int i=1;i<=n;i++){
13         string st;
14         cin>>st;
15         int x,y;
16         x=st[0];y=st[1];
17         vis[st[0]]=1;
18         vis[st[1]]=1;
19         vhash[x][y]++;vhash[y][x]++;
20         gin[x]++;
21         gin[y]++;
22     }
23 }
24 
25 int ans[11100],cnt=0;
26 
27 void dfs(int pos){
28     for(int i='A';i<='Z';i++)
29     if(vhash[i][pos]>0){
30         vhash[i][pos]--;//删边大法好
31         vhash[pos][i]--;
32         dfs(i);
33     }
34     for(int i='a';i<='z';i++)
35     if(vhash[i][pos]>0){
36         vhash[i][pos]--;
37         vhash[pos][i]--;
38         dfs(i);
39     }
40     ans[++cnt]=pos;
41 }
42 
43 void work(){
44     int tip=-1;
45     int qt=0;
46     for(int i='A';i<='Z';i++)
47     if(vis[i]==1){
48         if(gin[i]%2!=0)qt++;
49         if(tip==-1)tip=i;
50         if(gin[tip]%2==0&&gin[i]%2!=0){
51             tip=i;
52         }
53     }//两者效果一样,只不过是两个分开的解集
54     for(int i='a';i<='z';i++)
55     if(vis[i]==1){
56         if(gin[i]%2!=0)qt++;
57         if(tip==-1)tip=i;
58         if(gin[tip]%2==0&&gin[i]%2!=0){
59             tip=i;
60         }
61     }
62     
63     dfs(tip);
64     //判断it is very important 
65     if(qt&&qt!=2)cout<<"No Solution"<<endl;
66     else if(cnt<n+1)cout<<"No Solution"<<endl;
67     else {
68         for(int i=cnt;i>=1;i--)
69         cout<<char(ans[i]);
70         cout<<endl;
71     }
72 }
73 
74 int main(){
75     readp();
76     work();
77     return 0;
78 }

 

 1 #include<bits/stdc++.h>//万能头
 2 using namespace std;
 3 const int maxn=10000+10;
 4 int n,m,dis[maxn][maxn],s1=maxn,ans;//dis是用来存两点的连接
 5 char ru[maxn],a[maxn];//ru存度数,a存路径
 6 void out(){//写了个输出函数
 7     for(int i=ans;i>=1;i--)
 8     printf("%c",a[i]);
 9     cout<<endl;
10 }
11 void find(int i){//开始找欧拉路,i表示找的当前这个点
12         for(int j=1;j<=150;j++)//最大的小写z是肯定没超过150的,所以枚举点循环到150就行了
13             if(dis[i][j]>0){//如果两点之间有连通
14             dis[i][j]--;//毁图大法好
15             dis[j][i]--;
16             find(j);//搜索下一个点
17         }
18     a[++ans]=i;//记录路径
19     return ;
20 }
21 int main(){
22     cin>>m;
23     for(int i=1;i<=m;i++)
24     {
25         string s;
26         cin>>s;//这里我是采用string处理的,char也行不影响
27         dis[s[0]][s[1]]++;//记录路径,数组第一维表示当前的点,与第二维的点有,连接
28         dis[s[1]][s[0]]++;
29         ru[s[0]]++;//记录度数
30         ru[s[1]]++;
31      } 
32      int cnt=0,h=0;//开始找点
33     for(int i=1;i<=150;i++)//在找度数为奇数的点
34         if(ru[i]&1){
35             cnt++;
36             if(!h)h=i;
37         }
38     if(!h)//找不到奇点,就是另外找点
39         for(int i=0;i<150;i++)
40             if(ru[i]){h=i;break;}
41     if(cnt&&cnt!=2){
42         cout<<"No Solution";
43         return 0;
44     }
45     find(h);
46     if(ans<m+1){//这就是我之前所说的巧妙一点的方法,实际上只要搜完以后判断一下,点数是不是相等就行了,因为m组连边,必有m+1个点,前提是不重复
47         cout<<"No Solution";
48         return 0;
49     }
50     out();//输出
51     return 0;//完结散花
52 }

 

 

posted @ 2022-02-10 14:58  November&&Rain  阅读(46)  评论(0)    收藏  举报