题面传送门

题目大意:给你一张可能有重边的不保证联通的无向图,现在要在这个图上找出两条路径,恰好能覆盖所有边一次,根据边的编号输出方案,无解输出-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 (欧拉回路+构造)的更多相关文章

  1. D. Bear and Two Paths(贪心构造)

    D. Bear and Two Paths time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  2. hdu 4850 字符串构造---欧拉回路构造序列 递归+非递归实现

    http://acm.hdu.edu.cn/showproblem.php? pid=4850 题意:构造长度为n的字符序列.使得>=4的子串仅仅出现一次 事实上最长仅仅能构造出来26^4+4- ...

  3. BZOJ3724PA2014Final Krolestwo——欧拉回路+构造

    题目描述 你有一个无向连通图,边的总数为偶数.设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除).对于每个点对(u,v),你需要用一条长度为偶数(假设每条边长度为1)的 ...

  4. BZOJ3724 PA2014Final Krolestwo(欧拉回路+构造)

    如果没有长度为偶数的限制,新建一个点向所有奇点连边,跑欧拉回路即可,显然此时一定存在欧拉回路,因为所有点度数都为偶数. 考虑长度为偶数的限制,将每个点拆成两个点放进一个二分图里,那么每条原图中的边在二 ...

  5. CF1005F Berland and the Shortest Paths (树上构造最短路树)

    题目大意:给你一个边权为$1$的无向图,构造出所有$1$为根的最短路树并输出 性质:单源最短路树上每个点到根的路径 ,一定是这个点到根的最短路之一 边权为$1$,$bfs$出单源最短路,然后构建最短路 ...

  6. 转--python 黑魔法2

    Python 高效编程小技巧 个人博客:临风|刀背藏身 Python 一直被我拿来写算法题,小程序,因为他使用起来太方便了,各种niubi闪闪的技能点也在写算法的过程中逐渐被挖掘到,感谢万能的谷哥度娘 ...

  7. NOI前训练日记

    向别人学习一波,记点流水帐.17.5.29开坑. 5.29 早晨看了道据说是树状数组优化DP的题(hdu5542),然后脑补了一个复杂度500^3的meet in the middle.然后死T... ...

  8. IOI 2020 集训队作业胡扯

    首先安慰自己:做的没集训队快很正常-- 很正常-- 做不完也很正常-- 很正常-- 全都不会做也很正常-- 很正常-- 表格 试题一 完成情况 试题二 完成情况 试题三 完成情况 cf549E cf6 ...

  9. 使用Java8 Files类读写文件

    Java8 Files类的newBufferedReader()和newBufferedWriter()方法 这两个方法接受Path类型的参数.Path 类是Java8 NIO中的接口.可以由Path ...

随机推荐

  1. Android之利用EventBus进行数据传递

    在项目中,不可避免的要在两个页面之间进行数据的传递,就算不传递,也需要进行刷新之类的,我们根据Google提供的库类方法,也是可以做的,主要有广播broadcastreceiver,startacti ...

  2. [Codeforces Round495A] Sonya and Hotels

    [题目链接] https://codeforces.com/contest/1004/problem/A [算法] 直接按题意模拟即可 时间复杂度 :O(NlogN) [代码] #include< ...

  3. 8.22 NOIP 模拟题

      8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...

  4. codevs1163访问艺术馆(树形dp)

    1163 访问艺术馆  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master   题目描述 Description 皮尔是一个出了名的盗画者,他经过数月的精心准备, ...

  5. zookeeper集群安装及使用详解

    1. Zookeeper简介 ZooKeeper是一个开源的分布式框架,提供了协调分布式应用的基本服务.它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronizatio ...

  6. android:autoLink

    android:autoLink 显示URL链接 TextView识别链接的方式有两种,一种是自动识别链接和HTML解析链接 1)自动识别链接 <!-- android:autoLink=&qu ...

  7. 【BZOJ1483】[HNOI2009]梦幻布丁(平衡树启发式合并+并查集)

    题目: BZOJ1483 分析: (这题码了一下午,码了近250行,但是意外跑的比本校各位神仙稍快,特写博客纪念) 首先能看出一个显然的结论:颜色段数只会变少不会变多. 我们考虑用并查集维护区间,对于 ...

  8. ACM_Alien And Password

    Alien And Password Time Limit: 2000/1000ms (Java/Others) Problem Description: Alien Fred wants to de ...

  9. [转]linux之at指令详解

    转自:http://www.2cto.com/os/201409/336183.html 指令:at定时任务,指定一个时间执行一个任务,只能执行一次. 语法:# at [参数] [时间]at> ...

  10. js 计算时间差

    function GetDateDiff(startDate,endDate) { var startTime = new (<any>Date)(Date.parse(startDate ...