CodeForces 589H Tourist Guide
题目大意
给定$n$个点$m$条边的无向图,有$K$个关键点,你要尽可能的让这些关键点两两匹配,使得所有点对之间可以通过简单路径连接且任意两个简单路径没有重复的边(可以是共同经过一个点),输出每一条这样的路径。
$K\leq n,m\leq 5\times 10^4$
题解
很显然对于每一个连通块,当且仅当它有奇数个关键点,那么它会有一个关键点没有被配对,否则一定可以满足两两配对。
考虑该联通块的任意一棵生成树,不考虑是否经过了同一条边,任意两两沿着树上简单路径染边。
若有$(a,b)\cap (c,d) = (p,q)$其中$(x,y)$表示从$x,y$之间的简单路径(设$a,c$在$p$的同侧)。
那么只需要令$a,c$配对,$c,d$配对即可。
至于方案数,任意选择一棵生成树进行搜索即可,$G_x$表示以$x$为根的子树内没有配对的点是多少(若没有则$G_x=0$)。
枚举$x$的每个儿子$v$,若$G_v=0$就忽略,否则,若$G_x=0$,那么令$G_x=G_v$,不然就新建一条以$x$为$lca$的,一端是$G_x$一端是$G_v$的路径,再让$G_x=0$即可。
复杂度$O(n)$。
#include<bits/stdc++.h>
#define LL long long
#define M 100020
using namespace std;
namespace IO{
const int BS=(1<<20)+5; int Top=0;
char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[20]; const char *fin=OT+BS-1;
char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
void flush(){fwrite(OT,1,OS-OT,stdout);}
void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;}
void write(int x){
if(!x){Putchar('0');return;} if(x<0) x=-x,Putchar('-');
while(x) SS[++Top]=x%10,x/=10;
while(Top) Putchar(SS[Top]+'0'),--Top;
}
int read(){
int nm=0,fh=1; char cw=Getchar();
for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
}
using namespace IO;
int n,K,m,fs[M],to[M],G[M],nt[M],fa[M],u[M],v[M],t[M],tot,tmp;
int s1[M],s2[M]; bool vs[M];
#define link(a,b) nt[tmp]=fs[a],fs[a]=tmp,to[tmp++]=b
#define ins(a,b,c) tot++,u[tot]=a,v[tot]=b,t[tot]=c
void dp(int x){
G[x]=vs[x]?x:0;
for(int i=fs[x];i!=-1;i=nt[i]){
if(fa[to[i]]) continue;
fa[to[i]]=x,dp(to[i]);
if(!G[to[i]]) continue;
if(!G[x]) G[x]=G[to[i]];
else ins(G[x],G[to[i]],x),G[x]=0;
}
}
void opt(int x,int y,int k){
int tp1=0,tp2=0;
while(x!=k) s1[++tp1]=x,x=fa[x];
while(y!=k) s2[++tp2]=y,y=fa[y];
write(tp1+tp2),Putchar(' ');
for(int i=1;i<=tp1;i++) write(s1[i]),Putchar(' '); write(k);
for(int i=tp2;i>=1;i--) Putchar(' '),write(s2[i]); Putchar('\n');
}
int main(){
n=read(),m=read(),K=read(),memset(fs,-1,sizeof(fs));
for(int i=1;i<=m;i++){int x=read(),y=read();link(x,y),link(y,x);}
for(int i=1;i<=K;i++) vs[read()]=true;
for(int i=1;i<=n;i++) if(!fa[i]) fa[i]=i,dp(i);
write(tot),Putchar('\n');
for(int i=1;i<=tot;i++) opt(u[i],v[i],t[i]);
flush(); return 0;
}
CodeForces 589H Tourist Guide的更多相关文章
- [uva] 10099 - The Tourist Guide
10099 - The Tourist Guide 题目页:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemi ...
- UVa10099_The Tourist Guide(最短路/floyd)(小白书图论专题)
解题报告 题意: 有一个旅游团如今去出游玩,如今有n个城市,m条路.因为每一条路上面规定了最多可以通过的人数,如今想问这个旅游团人数已知的情况下最少须要运送几趟 思路: 求出发点到终点全部路其中最小值 ...
- floyd类型题UVa-10099-The Tourist Guide +Frogger POJ - 2253
The Tourist Guide Mr. G. works as a tourist guide. His current assignment is to take some tourists f ...
- codeforces 340C Tourist Problem
link:http://codeforces.com/problemset/problem/340/C 开始一点也没思路,赛后看别人写的代码那么短,可是不知道怎么推出来的啊! 后来明白了. 首先考虑第 ...
- codeforces 340C Tourist Problem(公式题)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Tourist Problem Iahub is a big fan of tou ...
- Codeforces 732F. Tourist Reform (Tarjan缩点)
题目链接:http://codeforces.com/problemset/problem/732/F 题意: 给出一个有n个点m条边的无向图,保证联通,现在要求将所有边给定一个方向使其变成有向图,设 ...
- codeforces 340C Tourist Problem(简单数学题)
题意:固定起点是0,给出一个序列表示n个点,所有点都在一条直线上,其中每个元素代表了从起点到这个点所走的距离.已知路过某个点不算到达这个点,则从起点出发,到达所有点的方案有许多种.求所有方案走的总路程 ...
- CodeForces 732F Tourist Reform
边双连通分量. 这题有一点构造的味道.一个有向图,经过强连通缩点之后会形成一个有向无环图. 如果将最大的强连通分量放在顶端,其余的强连通分量都直接或间接指向他,那么这样就构造出了符合要求的图. 接下来 ...
- CodeForces - 76F:Tourist (旋转坐标系,LIS)
pro:有一个驴友,以及给定N个表演地点xi和时间ti,驴友的速度不能超过V. 问他在起点为原点和不设置起点的情况下分别最多参观多少个表演. sol:BZOJ接飞饼见过:clari也在camp的DP专 ...
随机推荐
- 【Tech】CAS多机部署Server和Java Client端
昨天尝试把cas的java client端部署到另外一台机器,结果就有问题了.(localhost部署cas server和java client端参见:http://www.cnblogs.com/ ...
- 以太网100Mhz频率为什么可以达到带宽1000Mbps
转: https://wenku.baidu.com/view/353ea8ecb0717fd5370cdc0b.html
- Hadoop程序基础模板
分布式编程相对复杂,而Hadoop本身蒙上大数据.云计算等各种面纱,让很多初学者望而却步.可事实上,Hadoop是一个很易用的分布式编程框架,经过良好封装屏蔽了很多分布式环境下的复杂问题,因此,对普通 ...
- jsonp跨域总结
同源限制: 浏览器不允许一个域的脚本请求另一个域的文档,通俗来说,不允许访问不同协议.不同域名或不同端口的文档 跨域处理方法: 1.jsonp 前提: 浏览器虽然对ajax请求做出了限制,但scrip ...
- php数组函数-array_flip()
array_flip()函数返回一个反转后的数组,如果同一个值出现多次,则最 后一个键名作为它的值,所有其他的键名将丢失. 如果原数组中的值得数据类型不是字符串或整数,函数将报错. array_fli ...
- iOS面试必备-iOS基础知识
近期为准备找工作面试,在网络上搜集了这些题,以备面试之用. 插一条广告:本人求职,2016级应届毕业生,有开发经验.可独立开发,低薪求职.QQ:895193543 1.简述OC中内存管理机制. 答:内 ...
- Vue.js学习笔记 第八篇 组件
全局注册组件 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...
- 一步一步粗谈linux文件系统(三)----超级块(superblock)【转】
本文转载自:https://blog.csdn.net/fenglifeng1987/article/details/8302921 超级块是来描述整个文件系统信息的,可以说是一个全局的数据结构,可以 ...
- 字符串问题之 去掉字符串中连续出现K个0的子串
字符串中刚好出现K个连续的‘O’,则把K个连续‘O’字符去除,返回处理后的字符串 比如 str="AOOOOOBOOO" k=3, 返回“AOOOOOB” 这个题的解决思路也有 ...
- java基础(5)-集合类1
集合的由来 数组是很常用的一种数据结构,但假如我们遇到以下这样的的问题: 容器长度不确定 能自动排序 存储以键值对方式的数据 如果遇到这样的情况,数组就比较难满足了,所以也就有了一种与数组类似的数据结 ...