题目描述

给定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. 阿里云k8s部署zookeeper集群

    1. 阿里云k8s创建有状态应用 StatefulSet ,  选择使用模板创建 可以创建自定义模板 apiVersion: apps/v1 kind: StatefulSet metadata: c ...

  2. bat启动OpenOffice4

    start "" /d "C:\Program Files (x86)\OpenOffice 4\program" "soffice.exe" ...

  3. 启动3ds Max报 d3dx9_43.dll丢失 解决方法

    d3dx9_43.dll文件与Microsoft DirectX关联.负责启动基于Windows的游戏和高级图形程序. 在360安全卫士上搜索了 DirectX 下载了这个修复工具 运行应用 点击修复 ...

  4. 15 SpringMVC的入门案例

    1.入门程序的需求 2.搭建开发环境 <1>Create New Project <2>创建一个webapps <3>设置maven路径和解决maven项目创建过慢 ...

  5. ORACLE存储过程,循环语法和游标

    1.定义所谓存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过编译后存储在数据库系统中.在使用时候,用户通过指定已经定义的存储过程名字并给出 ...

  6. YARN-HA高可用集群搭建

    YARN-HA配置 1. YARN-HA工作机制 1.1 官方文档:http://hadoop.apache.org/docs/r2.7.2/hadoop-yarn/hadoop-yarn-site/ ...

  7. 论文笔记 XGBoost: A Scalable Tree Boosting System

    XGBoost是boosting算法的其中一种.Boosting算法的思想是将许多弱分类器集成在一起形成一个强分类器,其更关注与降低基模型的偏差.XGBoost是一种提升树模型(Gradient bo ...

  8. Navicat premium工具转储数据表的结构时,datatime字段报错

    Navicat premium工具导出数据库: Navicat premium工具导入数据库: 运行SQL文件,遇到的错误,红色下划线提示,发现:(SQL文件的时间有问题) 不是insert语句有问题 ...

  9. java之struts2的action优化配置

    当一个Action处理类中处理多个业务时,action的配置 文件将会急剧增加,导致配置文件很臃肿的问题. struts2提供了两种方案来解决这个问题.一种是动态方法调用,另一种是使用通配符来配置Ac ...

  10. IIS初始化设置预加载,解决程序池被回收第一次访问慢问题

    问题现象: 部署到IIS上的项目,第一次访问比较慢,有时后空闲一段时间去访问也会很慢,经常隔天访问也会慢.这就是IIS回收导致的问题,IIS回收把程序池的内存释放,网站就相当与重启的状态,被回收后,我 ...