@bzoj - 3724@ PA2014Final Krolestwo
@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的更多相关文章
- 【刷题】BZOJ 3724 PA2014Final Krolestwo
Description 你有一个无向连通图,边的总数为偶数. 设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除).对于每个点对(u,v),你需要用一条长度为偶数(假设每 ...
- bzoj 3728: PA2014Final Zarowki
3728: PA2014Final Zarowki Description 有n个房间和n盏灯,你需要在每个房间里放入一盏灯.每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮.你可 ...
- BZOJ3724 PA2014Final Krolestwo(欧拉回路+构造)
如果没有长度为偶数的限制,新建一个点向所有奇点连边,跑欧拉回路即可,显然此时一定存在欧拉回路,因为所有点度数都为偶数. 考虑长度为偶数的限制,将每个点拆成两个点放进一个二分图里,那么每条原图中的边在二 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
- BZOJ 题目整理
bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
随机推荐
- python爬虫需要掌握哪些知识点
1.熟练掌握Python语言 2.熟练掌握JS/HTML/CSS,了解HTTP协议. 3.熟练使用chrome 4.爬虫框架 推荐几个大神的教学干货,大家共同进步! https://zhuanlan. ...
- multipart_formdata
import requests def sendImg(img_path, img_name, img_type='image/jpeg'): """ :param im ...
- 前端自动化构建之gulp
前言 之前学完html的基础后就去学js框架了,每次都是用脚手架搭好的文件,在无形中体验了一波前端自动化带来的方便.然后前一段时间才开始学习前端自动化. 基本介绍 gulp说得简单一点就是一个自动化把 ...
- PIC单片机编译器自带的延时程序
https://wenku.baidu.com/view/3c94e2934028915f814dc205.html
- Java学习之路【第一篇】:前言
Java 语言概述 一.什么是Java语言 Java语言是美国Sun公司(Stanford University Network),在1995年推出的高级的编程语言.所谓编程语言,是计算机的语言,人们 ...
- JavaScript 简版-菜鸟中的菜鸟2
JavaScript 输出 JavaScript 没有任何打印或者输出的函数. JavaScript 显示数据 JavaScript 可以通过不同的方式来输出数据: 使用 window.alert() ...
- PAT1033 旧键盘打字 (20分) (关于测试点4超时问题)
1033 旧键盘打字 (20分) 旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 ...
- Rocket - diplomacy - ValName
https://mp.weixin.qq.com/s/so-2x5KLfYF0IMCCqNThwQ 简单调试ValName实现: 1. 使用 Desugar之后如下: ...
- Chisel3 - Tutorial - VendingMachine
https://mp.weixin.qq.com/s/tDpUe9yhwC-2c1VqisFzMw 演示如何使用状态机. 参考链接: https://github.com/ucb-bar/ch ...
- MyBatis特性详解
缓存简介 一般我们在系统中使用缓存技术是为了提升数据查询的效率.当我们从数据库中查询到一批数据后将其放入到混存中(简单理解就是一块内存区域),下次再查询相同数据的时候就直接从缓存中获取数据就行了. 这 ...