题目描述

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

解析

毒瘤字符串读入

我就是不喜欢邻接矩阵,你咬我啊。

首先看到题目,由于存在n个不相同的无序字母对,且答案中要求题给字母对两字母相邻,容易分析出每个在字母对中出现的字母在答案中都至少要出现一次。即,如果数据有解,必然有出现字母种类\(<=\)n。

接下来看题目给出的另一条件,其要求我们构造一个含\(n+1\)个字母的含有所有给定字母对的字符串,并且每个字母对的两个字母需要相邻。那么就意味着在答案中一个字母对不能重复出现,否则字符串长度至少为\(n+2\)。

“相邻”是一种显而易见的抽象关系,我们在处理抽象关系时,往往要想到利用图论的特性限制这些抽象关系。

也就是说,我们把每个字母看成点,如果两个字母相邻,我们就在其间连一条无向边。那么连完之后,我们会发现我们要构造的答案其实就是一条路径,答案就是路径上的点。并且这条路径要在经过所有点的情况下不经过重复的边,因为经过了重复的边等同于一个字母对出现了两次,这是题目不允许的。

分析到这里,是不是很熟悉?

是的,这显然是要求一个欧拉路,那么我们直接求就行了。

这里给出欧拉路存在的条件:

  1. 无向图是连通图
  2. 图中恰好有两个节点度数为奇数,其余节点度数都为偶数。

感性证明:1就不用证了,只要稍微想想就能明白。。。对于2,其实奇数点就是欧拉路的起点和终点。显然,如果一个点度数为偶数,那么它可以被一条路径进入至多度数/2次,一条路径也可以从这个点出去至多度数/2次。如果一个点度为奇数,那么一条路径在进进出出它偶数次后,最后一次要不然是从这个点出去要不然是从某个点到这个点。

所以我们只要通过一些特判对不构成欧拉路的图输出无解就得了。

顺便也讲一下为什么要回溯时用栈来储存路径,而不是dfs时边往下搜边记录。

dfs时,系统栈如果遇到死路,不代表这个图就没有欧拉路了,因为dfs进程还在继续进行。意思就是说我们要记的路径和系统栈回溯时经过的路径是很可能不同的。

为什么呢?我们要输出的显然是在搜索树上一条符合要求的搜索路径,就是要搜到底,搜到把图中所有点都遍历到之后在再回溯时的路径,我们记下来才是对的。而系统栈回溯的时候,可能是因为走到了错误的分支,这个时候我们要是也记下来,毫无疑问是错的。

所以,我们等到系统栈因为搜索树最后一层都搜完而执行回溯时再记录路径。

参考代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 2010
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
vector<int> g[N];
int m,n,top,minn=INF,deg[N];
char stack[N];
bool v[N][N];
inline void euler(int x)
{
for(int i=0;i<g[x].size();++i){
int y=g[x][i];
if(v[x][y]||v[y][x]) continue;
v[x][y]=v[y][x]=1;
euler(y);
}
stack[++top]=x;
}
int main()
{
m=read();
for(int i=1;i<=m;++i){
char s[3];
scanf("%s",s);
int x=s[0],y=s[1];
g[x].push_back(y),g[y].push_back(x);
deg[x]++,deg[y]++;
minn=min(minn,min((int)x,(int)y));
n=max(n,max((int)x,(int)y));
}
for(int i=minn;i<=n;++i)
sort(g[i].begin(),g[i].end());
int k=0,st=0;
for(int i=minn;i<=n;++i)
if(deg[i]&1){++k;if(!st)st=i;}//起点必须ASCII最小,且为奇点
if(!st)
for(int i=minn;i<=n;++i)
if(deg[i]){st=i;break;}//只有偶点
if(k!=2&&k){printf("No Solution");return 0;}//欧拉图存在性判断
euler(st);
if(top!=m+1){printf("No Solution");return 0;}//连通性判断
for(int i=top;i;--i) printf("%c",stack[i]);
return 0;
}

P1341 无序字母对[欧拉路]的更多相关文章

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

    P1341 无序字母对 题目提供者yeszy 标签 福建省历届夏令营 难度 提高+/省选- 最新讨论 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造 ...

  2. 洛谷 P1341 无序字母对 解题报告

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

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

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

  4. P1341 无序字母对【欧拉路径】- Hierholzer模板

    P1341 无序字母对 提交 24.87k 通过 6.80k 时间限制 1.00s 内存限制 125.00MB 题目提供者yeszy 难度提高+/省选- 历史分数100 提交记录 查看题解 标签 福建 ...

  5. 洛谷P1341 无序字母对[无向图欧拉路]

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一 ...

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

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一 ...

  7. 洛谷P1341 无序字母对【欧拉路】【dfs】

    题目:https://www.luogu.org/problemnew/show/P1341 题意:给定n对字母对,要求构造一个个数为n+1的字符串,使得每一个字母对都在里面出现过. 思路:这种题目都 ...

  8. P1341 无序字母对 欧拉回路

    题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 输入格式: 第一行输入一 ...

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

    题目链接: https://www.luogu.org/problemnew/show/P1341 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一 ...

随机推荐

  1. springboot-把web项目打成war包部署到外部tomcat

    将打包方式修改为war <packaging>war</packaging> 移除tomcat依赖或者将tomcat依赖scope改为provide 移除tomcat依赖 &l ...

  2. Harbor密码重置 密码修改 admin密码重置

    Harbor密码重置harbor现在是使用postgresql 数据库了.不再支持mysql,网上有N多重置Mysql密码的,可以略过了.我密码错了默认的Harbor12345 修改为: RedHat ...

  3. Metricbeat 轻量型指标采集器

    一.介绍 用于从系统和服务收集指标.从 CPU 到内存,从 Redis 到 Nginx,Metricbeat 能够以一种轻量型的方式,输送各种系统和服务统计数据. 1.系统级监控,更简洁(轻量型指标采 ...

  4. 简单的Lock死锁例子

    static void Main(string[] args) { lock (_lock1) { var t = new Thread(() => { lock (_lock1) { Cons ...

  5. mysql高并发配置

    mysql高并发配置 要在mysqld下设置1 修改back_log参数值:由默认的50修改为500.(每个连接256kb,占用:125M)back_log=500<pre> back_l ...

  6. jQuery无缝轮播图思路详解-唯品会

    效果图如上: 需求:图片自动轮播,鼠标移上停止播放,离开恢复播放,箭头切换图片. html代码 <!--轮播图大盒子开始--> <div class="wrap" ...

  7. vue+element+upload实现头像上传

    后台 @RequestMapping("/up") public JSONObject up(@RequestParam("picFile") Multipar ...

  8. 3.01定义常量之define

    [注:本程序验证是使用vs2013版] #include <stdio.h> #include <stdlib.h> #include <string.h> #pr ...

  9. 企业级容器管理平台 Rancher 介绍入门及如何备份数据

    企业级容器管理平台 Rancher 介绍入门及如何备份数据 是什么 Rancher 是一个为 DevOps 团队提供的完整的 Kubernetes 与容器管理解决方案的开源的企业级容器管理平台.它解决 ...

  10. [高清] Excel函数速记手册

    ------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...