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 ...
随机推荐
- HTTP的GET和POST请求
1.GET请求: 格式例如以下: request-line headers blank-line request-body 如图是我用wireshark截的一个GET请求的HTTP首部: GET请求发 ...
- BC - Zball in Tina Town (质数 + 找规律)
Zball in Tina Town Accepts: 541 Submissions: 2463 Time Limit: 3000/1500 MS (Java/Others) Memory ...
- MySQL hash分区(四)
具体描写叙述总结请看MySQL分区(一) 样例:该样例为本人个人学习总结分享->具体说明-->有问题欢迎前来交流 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...
- java学习笔记:eclipse的workspace和working set
我将这二个东西搞混了. 看上去,workspace 类似于VS里的解决方案,而working set则像VS里的解决方案文件夹,是个逻辑概念. VS里的解决方案是个文件,而eclipse里的works ...
- 初识bigdata时的一些技能小贴士
既然小豆腐如此给力,而且充分的利用主动学习的优势,已经有了迅速脑补,压倒式的优势,不过这只是表面而已,一切才刚刚开始,究竟鹿死谁手,还有待验证. 以上可以看到,小豆腐为什么拼命的要teach我们了么, ...
- 【Apio2009】Bzoj1179 Atm
目录 List Description Input Output Sample Input Sample Output HINT Solution Code Dfs 记忆化搜索 Position: h ...
- JavaSE综合项目演练
光阴似箭日月如梭,大家学习已经有了一段时间了,转眼间,从刚开始如何配置JDK已经到了现在快学完网络编程了.学了这么多,眼看就要进入下一个阶段了,数据库编程了,那么在进入下个阶段前,我们来完成一个综合性 ...
- TypeScript `infer` 关键字
考察如下类型: type PromiseType<T> = (args: any[]) => Promise<T>; 那么对于符合上面类型的一个方法,如何得知其 Prom ...
- JavaScript--确认(confirm 消息对话框)
confirm 消息对话框通常用于允许用户做选择的动作,如:“你对吗?”等.弹出对话框(包括一个确定按钮和一个取消按钮). 语法: confirm(str); 参数说明: str:在消息对话框中要显示 ...
- Django总结三
回顾: - 装饰器 模板 - def wrapper(func): def inner(*args, **args): 执行被执行函数之前的操作 res = func(*args, **args) 执 ...