P1341 无序字母对(欧拉回路+并查集)

 1 //并查集判联通,dfs求解欧拉回路
 2 #include<iostream>
 3 using namespace std;
 4 const int N=150;
 5 int mp[N][N];//邻接矩阵存图
 6 int d[N];//点的度数
 7 char res[N*N];//大于C(52,1)*C(51,1)/2,边数
 8 int n;//边数
 9 void dfs(int now)
10 {
11     for(int i=‘A‘;i<=‘z‘;i++)//没什么好说的
12     {
13         if(mp[now][i])
14         {
15             mp[now][i]=mp[i][now]=0;
16             dfs(i);
17         }
18     }
19     res[n--]=now;//走到底再存,得反过来,如果顺着来的话,数目有点麻烦(其实也是看别人反着来)
20 }
21 int fa[N];
22 int finds(int x)
23 {
24     while(fa[x]!=x)
25     {
26         x=fa[x];
27     }
28     return x;
29 }
30 int main(void)
31 {
32     cin>>n;
33     for(int i=‘A‘;i<=‘z‘;i++)
34     {
35         fa[i]=i;
36     }//并查集初始化
37     for(int i=1;i<=n;i++)
38     {
39         string s;
40         cin>>s;
41         mp[s[0]][s[1]]=mp[s[1]][s[0]]=1;
42         d[s[0]]++;//度数加一
43         d[s[1]]++;
44
45         int f1=finds(s[0]);
46         int f2=finds(s[1]);
47         fa[f1]=f2;//union
48     }
49     int cnt=0;//连通分量数
50     for(int i=‘A‘;i<=‘z‘;i++)
51     {
52         if(d[i]&&fa[i]==i)
53         {
54             cnt++;
55         }
56     }
57     if(cnt>1)
58     {
59         cout<<"No Solution"<<endl;
60         return 0;
61     }
62     cnt=0;//奇点数
63     int head=0;//欧拉回(通)路起点
64     for(int i=‘A‘;i<=‘z‘;i++)
65     {
66         if(d[i]&1)
67         {
68             cnt++;
69             if(head==0)
70             {
71                 head=i;
72             }
73         }
74     }
75     if(cnt&&cnt!=2)//奇点只能没有或者有两个
76     {
77         cout<<"No Solution"<<endl;
78         return 0;
79     }
80     if(!head)//如果没有奇点就找个最小的偶度点出发,注意如果有奇点必须从奇点出发(错了贼久)
81     {
82         for(int i=‘A‘;i<=‘z‘;i++)
83         {
84             if(d[i])
85             {
86                 head=i;
87                 break;
88             }
89         }
90     }
91     int tmp=n;
92     dfs(head);
93     for(int i=0;i<=tmp;i++)
94     {
95         cout<<res[i] ;
96     }
97     return 0;
98 }

原文地址:https://www.cnblogs.com/greenofyu/p/12231454.html

时间: 2024-11-13 04:17:32

P1341 无序字母对(欧拉回路+并查集)的相关文章

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

我永远信仰欧拉 欧拉回路是很经典的一道题目了 这题算是稍稍修改的模板题吧 欢迎指出错误 题目链接 思路 先判断能不能构成欧拉路径/回路 即度数为1的总点数为2或0的时候符合(前者为连通图,后者为回路) 这题是回路吧 如果不可以,结束 如果可以,dfs搜索路径(貌似搜索路径还有模板来着) 代码 代码短,我就不压了 1 #include<bits/stdc++.h> 2 #define maxn 257 3 bool G[maxn][maxn]; 4 int deg[maxn]; 5 char t

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

P1341 无序字母对 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一个正整数n. 以下n行每行两个字母,表示这两个字母需要相邻. 输出格式: 输出满足要求的字符串. 如果没有满足要求的字符串,请输出“No Solution”. 如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案 输入输出样例 输入样例#1: 4 a

HDU1116(欧拉回路+并查集)

先用并查集来判断图是否连通,然后再根据欧拉回路的出度和入度的性质来判断是否为欧拉回路. 关键是建边,我们可以把字符串看成是一条边,首字母为出发点,尾字母为目的点,建边. #include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <algorithm> #include <vector> #include <math.

HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)

题目链接 题意 : 有很多门,每个门上有很多磁盘,每个盘上一个单词,必须重新排列磁盘使得每个单词的第一个字母与前一个单词的最后一个字母相同.给你一组单词问能不能排成上述形式. 思路 :把每个单词看成有首字母指向尾字母的有向边,每个字母看成一个点,题中要求等效于判断图中是否存在一条路径经过每一条一次且仅一次,就是有向欧拉通路.统计个顶点的出入度,如果每个点的出入度都相同,那就是欧拉回路,如果有两个奇数度,那就是欧拉通路,除此之外,都不能满足要求.还有别忘了判断是否连通,此时用到并查集,图中所有的边

luogu P1341 无序字母对

P1341 无序字母对 直通 思路: 欧拉回路问题 坑点: ①第三个点出现了 5 ab ac ad ae af 这样的情况 所以我们需要加一点小优化: for(int i=0; i<=top; i++) { //特判第三个点... if(i==0) continue; if(!tmp[ans[i]][ans[i-1]]) { printf("No Solution"); return 0; } } ②我们还需要保证题目中给出的所有字母均在ans数组中出现,所以需要开2个vis数组

洛谷P1341 无序字母对

P1341 无序字母对 229通过 806提交 题目提供者yeszy 标签图论福建省历届夏令营 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 不知道哪里错 求解释 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一个正整数n. 以下n行每行两个字母,表示这两个字母需要相邻. 输出格式: 输出满足要求的字符串. 如果没有满足要求的字符串,

poj 2513 欧拉回路+并查集判断是否联通+Trie树

http://poj.org/problem?id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得以前看过,trie代替map,尤其当数据量特别大的时候 学到了: 1.Trie代替map的思想,可以在单词结尾的tree[i][tk]  这个i作为字符串对应的int值 ,当然这个int值也可以用于建立并查集 2.接上,通过并查集判断,所有的点在同一个集合图就是联通的,否则不联通,注意tree[i][tk]>0 表示是单词结尾, x=Find(x);//这句

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

题目链接: https://www.luogu.org/problemnew/show/P1341 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一个正整数n. 以下n行每行两个字母,表示这两个字母需要相邻. 输出格式: 输出满足要求的字符串. 如果没有满足要求的字符串,请输出"No Solution". 如果有多种方案,请输出前面的字

UVA - 10129 Play on Words(欧拉回路+并查集)

2.解题思路:本题利用欧拉回路存在条件解决.可以将所有的单词看做边,26个字母看做端点,那么本题其实就是问是否存在一条路径,可以到达所有出现过的字符端点.由于本题还要求了两个单词拼在一起的条件是前一个单词的右端点和本单词的左端点一样.所以这是一个有向图.根据结论:有向图的底图(忽略边的方向后的图)必须连通:有向图中最多只能有两个端点的入度不等于出度,且必须是其中一点的入度比出度小1,另一点的入度比出度大1.因此先判断端点是否都连通,再判断每个端点的度数是否满足结论即可. 那么,如何判断连通性呢?