@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:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
随机推荐
- select 下拉模糊查询
http://ivaynberg.github.io/select2/ https://github.com/ https://github.com/ivaynberg.github.io/selec ...
- for、forEach、for in、for of用法
循环遍历数组或者对象,for.forEach.for in . for of 使用最多 for循环 自Javascript诞生时就有,遍历数组,for 循环的语法如下: for (语句 1; 语句 2 ...
- UVALive3720
题目大意:见刘汝佳<算法竞赛入门经典——训练指南>P173. 解题思路: 问题可以转化为求共有多少条过点阵中的点的斜线.其中必定包含左斜线和右斜线,由于点阵式对称的,所以我们只需求出左右斜 ...
- Lightoj1356
题目链接:https://vjudge.net/problem/LightOJ-1356 题目大意: T个 test case,每个 test case 给出一个 N 个数的集合.请找出一个最大的子集 ...
- Python之日志处理(logging模块一基础)
转载自:https://www.cnblogs.com/yyds/p/6901864.html 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logg ...
- [json-server] RESTful API 中,取主数据时,同时获取多个关联子表的数据
项目背景: back-end:ASP.NET Core WebAPI front-end:Vue(+vue-router +vuex +axios)(webpack)(json-server + mo ...
- 八皇后问题求解java(回溯算法)
八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处 ...
- python之robotframework+pycharm测试框架
一.robotframework简介 Robot Framework是一款python编写的功能自动化测试框架.具备良好的可扩展性,支持关键字驱动,可以同时测试多种类型的客户端或者接口,可以进行分布式 ...
- [256个管理学理论]001.蝴蝶效应(Butterfly Effect)
蝴蝶效应(Butterfly Effect) 来自于大洋彼岸的让你看不懂的解释: 蝴蝶效应是指在一个动力系统中,初始条件下微小的变化能带动整个系统的长期的巨大的连锁反应,是一种混沌的现象.“蝴蝶效应” ...
- 02 . Nginx平滑升级和虚拟主机
Nginx虚拟主机 在真实的服务器环境,为了充分利用服务器资源,一台nginx web服务器会同时配置N个虚拟主机,这样可以充分利用服务器的资源,方便管理员的统一管理 配置nginx虚拟主机有三种方法 ...