CF36E Two Paths (欧拉回路+构造)
题目大意:给你一张可能有重边的不保证联通的无向图,现在要在这个图上找出两条路径,恰好能覆盖所有边一次,根据边的编号输出方案,无解输出-1
一道很不错的欧拉路径变形题
首先要知道关于欧拉路径的一种算法:Hierholzer算法
欧拉路径与欧拉回路
我们称度为奇数的点为奇点,度为偶数的点为偶点
从一个点开始走,把其它所有边都走了一遍,叫欧拉路径
从一个点开始走,把其它所有边都走了一遍又回到了这个点,叫欧拉回路
如果图中存在欧拉回路,所有点均为偶点,画画图就明白了
如果图中不存在或仅存在两个奇点,那么这个图存在欧拉路径,且路径的起点终点一定分别是这两个奇点。把起点终点连起来不就变成欧拉回路了么
欧拉回路一定是欧拉路径
Hierholzer算法
从图中的一个奇点开始dfs,每遍历到一条边,就在图中删去这条边(包括反向边),然后递归指向的节点
直到当前节点相连的所有边都被删掉之后,把当前节点推入一个栈中,回溯
如果原图存在欧拉回路,就能搜出欧拉回路。如果存在欧拉路径,就会搜出欧拉路径。
栈中存储的是路径的倒序点序列,而边序列就是每次递归前删掉的边构成的序列
实现比较简单
那这道题该怎么搞呢?
(1)如果图中有>2个连通块,一定无解
(2)如果只有1个连通块,分为0个奇点,2个奇点,4个奇点讨论,其它情况都是无解
0个奇点就是欧拉回路,断开其中任意一条边,把路径拆成两条就是答案
2个奇点就是欧拉路径,断开其中任意一条边,把路径拆成两条就是答案
4个奇点的话,挑两个奇点连起来,再跑欧拉路径就行啦
(3)如果有2个连通块,说明这两条路径分别在这两个连通块里
对于每个连通块而言,只能存在0个奇点和2个奇点两种情况,讨论一下就好啦
代码写得好丑啊TvT
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define N1 20010
using namespace std; template <typename _T> void read(_T &ret)
{
ret=; _T fh=; char c=getchar();
while(c<''||c>''){ if(c=='-') fh=-; c=getchar(); }
while(c>=''&&c<=''){ ret=ret*+c-''; c=getchar(); }
ret=ret*fh;
} struct Edge{
int to[N1*],nxt[N1*],del[N1*],head[N1],cte;
void ae(int u,int v)
{ cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
}e; int n,m,num;
int inc[N1],vis[N1],use[N1],stk[N1],tp;
void dfs1(int x,int id)
{
int j,v; vis[x]=id; num++;
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j];
if(!vis[v]) dfs1(v,id);
}
}
void euler(int x)
{
int j,v,la=;
for(j=e.head[x];j;j=e.nxt[j])
{
if(e.del[j]) continue;
v=e.to[j]; e.del[j]=; e.del[j^]=;
euler(v); stk[++tp]=j>>;
}
}
void fkdown(){ puts("-1"); exit(); }
int odd[N1],cnt_odd; void solve0(int id,int esum)
{
int i;
for(i=;i<=n;i++) if(vis[i]==id)
{
euler(i);
if(tp<esum) fkdown();
printf("%d\n",tp);
while(tp) printf("%d ",stk[tp--]);
puts("");
break;
}
}
void solve2(int id,int esum)
{
euler(odd[]);
if(tp<esum) fkdown(); //
printf("%d\n",tp);
while(tp) printf("%d ",stk[tp--]);
puts("");
} int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d",&m);
int i,j,x,y,cnt_compo=; n=; e.cte=;
if(m==) fkdown();
for(i=;i<=m;i++)
{
read(x), read(y), e.ae(x,y), e.ae(y,x);
inc[x]++, inc[y]++, use[x]=, use[y]=;
}
for(i=;i<=n;i++) if(use[i] && !vis[i]) cnt_compo++, dfs1(i,cnt_compo);
if(cnt_compo>) fkdown();
if(cnt_compo==){
for(i=;i<=n;i++) if(inc[i]&) odd[++cnt_odd]=i;
if(!cnt_odd){ for(i=;i<=n;i++) if(inc[i])
{
euler(i);
if(tp<m) fkdown();
printf("%d\n",tp-);
while(tp>) printf("%d ",stk[tp--]);
puts("");
puts("");
while(tp>) printf("%d ",stk[tp--]);
puts("");
break;
} }else if(cnt_odd==){ euler(odd[]);
if(tp<m) fkdown();
printf("%d\n",tp-);
while(tp>) printf("%d ",stk[tp--]);
puts("");
puts("");
while(tp>) printf("%d ",stk[tp--]);
puts(""); }else if(cnt_odd==){ e.ae(odd[],odd[]); e.ae(odd[],odd[]);
euler(odd[]);
if(tp-<m) fkdown();
while(tp)
{
if(stk[tp]>m) break;
tp--;
}
printf("%d\n",m+-tp);
for(i=m+;i>tp;i--) printf("%d ",stk[i]);
puts("");
tp--; printf("%d\n",tp);
while(tp) printf("%d ",stk[tp--]);
puts(""); }else fkdown();
}else{
int esum=; cnt_odd=; esum=;
for(i=;i<=n;i++)
{
if(!vis[i] || vis[i]==) continue;
if((inc[i]&)) odd[++cnt_odd]=i;
esum+=inc[i];
}
if(cnt_odd> || cnt_odd&) fkdown(); cnt_odd=; esum=;
for(i=;i<=n;i++)
{
if(!vis[i] || vis[i]==) continue;
if((inc[i]&)) odd[++cnt_odd]=i;
esum+=inc[i];
}
if(cnt_odd> || cnt_odd&) fkdown();
esum>>=;
if(!cnt_odd) solve0(,esum);
else if(cnt_odd==) solve2(,esum);
else fkdown(); cnt_odd=; esum=;
for(i=;i<=n;i++)
{
if(!vis[i] || vis[i]==) continue;
if((inc[i]&)) odd[++cnt_odd]=i;
esum+=inc[i];
}
esum>>=;
if(!cnt_odd) solve0(,esum);
else if(cnt_odd==) solve2(,esum);
else fkdown();
}
return ;
}
CF36E Two Paths (欧拉回路+构造)的更多相关文章
- D. Bear and Two Paths(贪心构造)
D. Bear and Two Paths time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- hdu 4850 字符串构造---欧拉回路构造序列 递归+非递归实现
http://acm.hdu.edu.cn/showproblem.php? pid=4850 题意:构造长度为n的字符序列.使得>=4的子串仅仅出现一次 事实上最长仅仅能构造出来26^4+4- ...
- BZOJ3724PA2014Final Krolestwo——欧拉回路+构造
题目描述 你有一个无向连通图,边的总数为偶数.设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除).对于每个点对(u,v),你需要用一条长度为偶数(假设每条边长度为1)的 ...
- BZOJ3724 PA2014Final Krolestwo(欧拉回路+构造)
如果没有长度为偶数的限制,新建一个点向所有奇点连边,跑欧拉回路即可,显然此时一定存在欧拉回路,因为所有点度数都为偶数. 考虑长度为偶数的限制,将每个点拆成两个点放进一个二分图里,那么每条原图中的边在二 ...
- CF1005F Berland and the Shortest Paths (树上构造最短路树)
题目大意:给你一个边权为$1$的无向图,构造出所有$1$为根的最短路树并输出 性质:单源最短路树上每个点到根的路径 ,一定是这个点到根的最短路之一 边权为$1$,$bfs$出单源最短路,然后构建最短路 ...
- 转--python 黑魔法2
Python 高效编程小技巧 个人博客:临风|刀背藏身 Python 一直被我拿来写算法题,小程序,因为他使用起来太方便了,各种niubi闪闪的技能点也在写算法的过程中逐渐被挖掘到,感谢万能的谷哥度娘 ...
- NOI前训练日记
向别人学习一波,记点流水帐.17.5.29开坑. 5.29 早晨看了道据说是树状数组优化DP的题(hdu5542),然后脑补了一个复杂度500^3的meet in the middle.然后死T... ...
- IOI 2020 集训队作业胡扯
首先安慰自己:做的没集训队快很正常-- 很正常-- 做不完也很正常-- 很正常-- 全都不会做也很正常-- 很正常-- 表格 试题一 完成情况 试题二 完成情况 试题三 完成情况 cf549E cf6 ...
- 使用Java8 Files类读写文件
Java8 Files类的newBufferedReader()和newBufferedWriter()方法 这两个方法接受Path类型的参数.Path 类是Java8 NIO中的接口.可以由Path ...
随机推荐
- 汉澳Sinox2014X64server高级桌面服务器版操作系统公布
汉澳Sinox2014X64server高级桌面服务器版操作系统公布 当你在现代城市夜空中看到一道闪电.屏幕中央闪过几个图形,转眼间变成美轮美奂的紫色空中天国,说明你来到了汉澳sinox2014世 ...
- Java与设计模式-适配器模式
适配器模式是开发中常常会用到的模式,Android开发中常常常使用到的各种adapter就属于适配器模式,连接各种数据库时也要用到适配器模式. 适配器模式在生活中的实例也随处可见,你托人在日本买了个电 ...
- 第四章、TIny4412 U-BOOT移植四 配置时钟频率源码分析【转】
本文转载自:http://blog.csdn.net/eshing/article/details/37542459 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 上 ...
- win32 API函数
cozy的博文 win32 API函数大全 (2008-03-15 16:28) 分类: 个人日记 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WN ...
- Gold Coins
http://poj.org/problem?id=2000 #include<stdio.h> ; int main() { int coin[N]; ,j,k; j = ; k = ; ...
- 我们的微信小程序开发
基于微信小程序的系统开发准备工作 腾讯推出微信小程序也有一段时间了,在各种行业里面也都掀起一阵阵的热潮,很多APP应用被简化为小程序的功能迅速推出,同时也根据小程序的特性推出各种独具匠心的应用,相对传 ...
- sql 查询出当天记录数据
select updatetime,NewComment,HistoryID,sum(1) over(partition by UpdateTime) from LPProjectHistoryord ...
- Java初级面试模拟1
1.简单介绍一下你的项目,说一下项目有什么模块 2.说说常见的集合有哪些吧 答:Map接口和Collection接口是所有集合框架的父接口: Collection接口的子接口包括:Set接口和List ...
- eclipse上ndk环境的搭建&&so文件的生成&&jni文件的调用
JNI是java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以调用java代码.JNI 是本地编程接口,Java和C/C++ ...
- 【Vijos1083/BZOJ1756】小白逛公园(线段树)
[写在前面]TYC (Little White) 真是太巨啦! 题目: Vijos1083 分析: 一眼看上去就是线段树啊-- 然而当我这种蒟蒻兴高采烈地把线段树模板敲了一半,却发现一个问题: 这子区 ...