@description@

你有一个无向连通图,边的总数为偶数。

设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除)。对于每个点对(u,v),你需要用一条长度为偶数(假设每条边长度为1)的路径将u和v连接。每条路径允许经过重复的点,但不允许经过重复的边。这k/2条路径之间也不能有重复的边。

原题链接。

@solution@

先不考虑路径长度必须为偶数,其实就是跑 k/2 条欧拉路径。

这个实现方法很多,讲一种这道题可以用的:建虚点 s,s 向所有奇点连虚边,跑欧拉回路,然后断开所有虚边。

考虑路径长度为偶数,联想到二分图。考虑一个点拆成黑白两点,原来的一条边 (u, v) 对应了 u 的黑/白点连向 v 的白/黑点。

如果虚点 s 只向奇点的黑点连边,则跑出来的欧拉回路一定是路径长度为偶数。

不过这个拆点中,一条边 (u, v) 只能对应 u 的黑/白点连向 v 的白/黑点中一种情况。

所以我们要加以选择,使得建出来的新图中每个点的度数依然为偶数。

因为白点度数 + 黑点度数 = 原图点度数,所以我们只需要白点度数为偶数即可。

考虑将问题转化一下:给每条边 (u, v) 定向成 u -> v 或 v -> u,定向后每个点的出边即这个点白点连出去的边。

这个问题就是经典问题了,建出任意一棵生成树(一般选 dfs 树)后,非树边随便选,树边自下而上调整,即可保证每个白点的度数为偶数。

@accepted code@

#include <cstdio>

const int MAXN = 2*250000;

struct Graph{
struct edge{
int to, id; bool tag;
edge *nxt, *rev;
}edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt;
Graph() {ecnt = edges;}
void addedge(int u, int v, int i) {
edge *p = (++ecnt), *q = (++ecnt);
p->to = v, p->id = i, p->nxt = adj[u], adj[u] = p;
q->to = u, q->id = i, q->nxt = adj[v], adj[v] = q;
p->rev = q, q->rev = p;
// printf("! %d %d %d\n", u, v, i);
}
}G1, G2;
#define rep(G, x) for(Graph::edge *p=G.adj[x];p;p=p->nxt) int dfn[MAXN + 5], oud[MAXN + 5], dcnt;
void dfs(int x, int f) {
dfn[x] = (++dcnt);
rep(G1, x) {
if( p->to == f ) continue;
if( dfn[p->to] ) {
if( dfn[p->to] < dfn[x] )
G2.addedge(2*x, 2*p->to-1, p->id), oud[x]++;
}
else {
dfs(p->to, x);
if( oud[p->to] & 1 )
G2.addedge(2*p->to, 2*x-1, p->id), oud[p->to]++;
else G2.addedge(2*p->to-1, 2*x, p->id), oud[x]++;
}
}
} Graph::edge *stk[MAXN + 5]; int tp; void dfs2(int x) {
// printf("! %d\n", x);
for(;G2.adj[x];) {
Graph::edge *p = G2.adj[x]; G2.adj[x] = G2.adj[x]->nxt;
if( p->tag ) continue;
p->tag = p->rev->tag = true;
dfs2(p->to);
stk[++tp] = p->rev;
}
} int deg[MAXN + 5]; int main() {
int n, m; scanf("%d%d", &n, &m);
for(int i=1;i<=m;i++) {
int a, b; scanf("%d%d", &a, &b);
G1.addedge(a, b, i), deg[a]++, deg[b]++;
}
for(int i=1;i<=n;i++)
if( deg[i] & 1 ) G2.addedge(0, 2*i-1, -1);
dfs(1, -1), dfs2(0);
int lst = 1;
/*
for(int i=1;i<=tp;i++)
printf("%d ", stk[i]->id);
puts("");
*/
for(int i=2;i<=tp;i++) {
if( stk[i]->id == -1 ) {
printf("%d %d %d\n", (stk[lst]->to + 1)/2, (stk[i]->rev->to + 1)/2, i - lst - 1);
for(int j=lst+1;j<=i-1;j++) {
printf("%d%c", stk[j]->id, j + 1 == i ? '\n' : ' ');
}
i++, lst = i;
}
}
}

@details@

需要注意欧拉回路的实现,要用类当前弧优化的方法进行优化,不然时间复杂度不正确。

@bzoj - 3724@ PA2014Final Krolestwo的更多相关文章

  1. 【刷题】BZOJ 3724 PA2014Final Krolestwo

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

  2. bzoj 3728: PA2014Final Zarowki

    3728: PA2014Final Zarowki Description 有n个房间和n盏灯,你需要在每个房间里放入一盏灯.每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮.你可 ...

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

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

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. 关于Docker的实践

    docker 安装 wget -qO- https://get.docker.com/ | sh 镜像 images search pull commit build tag 查看本地镜像:docke ...

  2. LaunchScreen作为启动图设置,修改无效的解决方案

    原有的推流APP用launchScreen做的启动图,现在要修改一张,发现修改无效. 当前测试的方法有 1,重启Xcode  卸载app 清楚xcode缓存 2,修改launchScreen.stor ...

  3. Angular SPA基于Ocelot API网关与IdentityServer4的身份认证与授权(二)

    上文已经介绍了Identity Service的实现过程.今天我们继续,实现一个简单的Weather API和一个基于Ocelot的API网关. 回顾 <Angular SPA基于Ocelot ...

  4. .net core HttpClient 使用之消息管道解析(二)

    一.前言 前面分享了 .net core HttpClient 使用之掉坑解析(一),今天来分享自定义消息处理HttpMessageHandler和PrimaryHttpMessageHandler ...

  5. 使用webstorm 搭建 vue 开发环境

    一.首先安装 node.js 安装成功后在cmd里面使用:node -v 命令查看安装是否成功 下载链接: 链接:https://pan.baidu.com/s/1CL9J4Ryp3sL0zPYKJy ...

  6. CSS基础选择器总结

    基础选择器 作用 特点 使用情况 用法 标签选择器 可以选出所有相同的标签,比如p 不能差异化选择 较多 p {color:red;} 类选择器 可以选出1个或多个标签 可以根据需求选择 非常多 .n ...

  7. 【JavaScript数据结构系列】00-开篇

    [JavaScript数据结构系列]00-开篇 码路工人 CoderMonkey 转载请注明作者与出处 ## 0. 开篇[JavaScript数据结构与算法] 大的计划,写以下两部分: 1[JavaS ...

  8. Oracle 利用PLSQL一分钟将表结构(PROJ),从A库移植到B库,一分钟将A库中表数据移植到B库中!!!

    导读(苦恼) 做多个项目的时候,可能会有这样的需求,需要把A项目中的某些功能移植到B项目上:移植途中,牵扯到顺便把表也要一块移植过去,若表字段较少,那还好,可能耗费10分钟就搞完了,万一碰上几十个字段 ...

  9. [SD心灵鸡汤]002.每月一则 - 2015.06

    1.用最多的梦面对未来 2.自己要先看得起自己,别人才会看得起你 3.一个今天胜过两个明天 4.要铭记在心:每天都是一年中最美好的日子 5.乐观者在灾祸中看到机会:悲观者在机会中看到灾祸 6.有勇气并 ...

  10. 微信小程序入门与实战(最新完整版)教程

    微信小程序入门与实战(最新完整版) 如图地址:下载地址在底部 |- 第1章 什么是微信小程序? - 0 B |- 第2章 小程序环境搭建与开发工具介绍 - 0 B |- 第3章 从一个简单的“欢迎“页 ...