「题解」NWRRC2017 Grand Test
本文将同步发布于:
题目
题目链接:洛谷 P7025、gym101612G。
题意概述
给你一张有 \(n\) 个点 \(m\) 条边的无向图,无重边无自环,请你求出两个点 \(s,t\) 使得 \(s,t\) 之间有三条不重合的简单路径。
\(1\leq\sum n,\sum m\leq 10^5\)
题解
探究图的性质
考虑到本题是无向图,我们不难想到一个引理。
引理:无向图的 dfs 树上只存在树边和返祖边。
考虑到 dfs 树中只会存在树边、返祖边、横叉边,因此我们只需要证明无向图的 dfs 树上不存在横叉边即可。
考虑反证法。
假设存在一条横叉边 \((u,v)\),目前遍历到 \(u\),\(v\) 在之前被访问过,根据横叉边的定义,\(v\) 不是 \(u\) 的祖先。
根据深度优先搜索的深度优先原则,此时一定访问完了所有与 \(v\) 相连的节点,但 \(u\) 却未被访问到,造成矛盾,假设不成立,引理得证。
利用性质构造方案
考虑到 dfs 树上只有额外的返祖边,我们不难构造出一种方案。
对于一个点 \(u\),如果它的两棵子树内存在两个节点 \(x,y\) 使得有两条返祖边 \((x,p_1),(y,p_2)\) 满足 \(p_1,p_2\) 是节点 \(u\) 的祖先,则 \(s=p_1,t=u\) 符合条件。
画成图长下面这样:

充分性十分显然,下面我们考虑证明必要性。即不存在上述情况,也有满足条件的三条路径和两个节点。
不难发现这是不可能的,因为只要存在起点与终点,它们在 dfs 树上必然是祖先关系,因此一定满足上述情况,矛盾。
因此我们证明了这个条件的充分必要性,用 tarjan 算法判定即可。时间复杂度 \(\Theta(n)\)。
参考程序
#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
static char buf[1<<21],*p1=buf,*p2=buf;
#define flush() (fwrite(wbuf,1,wp1,stdout),wp1=0)
#define putchar(c) (wp1==wp2&&(flush(),0),wbuf[wp1++]=c)
static char wbuf[1<<21];int wp1;const int wp2=1<<21;
inline int read(void){
reg char ch=getchar();
reg int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))res=10*res+(ch^'0'),ch=getchar();
return res;
}
inline void write(reg int x){
static char buf[32];
reg int p=-1;
if(x<0) x=-x,putchar('-');
if(!x) putchar('0');
else while(x) buf[++p]=(x%10)^'0',x/=10;
while(~p) putchar(buf[p--]);
return;
}
const int MAXN=1e5+5;
int n,m;
vector<int> G[MAXN];
int fa[MAXN];
int tim,dfn[MAXN],rnk[MAXN],low[MAXN],ed[MAXN],clow[MAXN],ced[MAXN];
int s,t;
inline void tarjan(reg int u,reg int father){
fa[u]=father;
dfn[u]=low[u]=clow[u]=++tim;
rnk[tim]=u;
ed[u]=ced[u]=u;
for(int v:G[u])
if(v!=father){
if(!dfn[v]){
tarjan(v,u);
if(low[v]<low[u]){
clow[u]=low[u],ced[u]=ed[u];
low[u]=low[v],ed[u]=ed[v];
}
else if(low[v]<clow[u])
clow[u]=low[v],ced[u]=ed[v];
}
else{
if(dfn[v]<low[u]){
clow[u]=low[u],ced[u]=ed[u];
low[u]=dfn[v],ed[u]=u;
}
else if(dfn[v]<clow[u])
clow[u]=dfn[v],ced[u]=u;
}
}
if(!s&&!t&&clow[u]<dfn[u])
s=u,t=rnk[clow[u]];
return;
}
inline vector<int> getPath(reg int son,int father){
vector<int> res;
for(int p=son;p!=father;p=fa[p])
res.push_back(p);
res.push_back(father);
return res;
}
inline vector<int> reverse(vector<int> a){
reverse(a.begin(),a.end());
return a;
}
inline vector<int> merge(vector<int> a,vector<int> b){
a.insert(a.end(),b.begin(),b.end());
return a;
}
int main(void){
reg int T=read();
while(T--){
n=read(),m=read();
for(reg int i=1;i<=n;++i)
G[i].clear();
for(reg int i=1;i<=m;++i){
static int u,v;
u=read(),v=read();
G[u].push_back(v),G[v].push_back(u);
}
tim=0,fill(dfn+1,dfn+n+1,0);
s=0,t=0;
for(reg int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i,0);
if(!s&&!t)
write(-1),putchar('\n');
else{
write(s),putchar(' '),write(t),putchar('\n');
vector<int> ans1=getPath(s,t);
write(ans1.size()),putchar(' ');
for(reg int i=0,siz=ans1.size();i<siz;++i)
write(ans1[i]),putchar(i==siz-1?'\n':' ');
vector<int> ans2=merge(reverse(getPath(ed[s],s)),reverse(getPath(t,rnk[low[s]])));
write(ans2.size()),putchar(' ');
for(reg int i=0,siz=ans2.size();i<siz;++i)
write(ans2[i]),putchar(i==siz-1?'\n':' ');
vector<int> ans3=merge(reverse(getPath(ced[s],s)),getPath(rnk[clow[s]],rnk[clow[s]]));
write(ans3.size()),putchar(' ');
for(reg int i=0,siz=ans3.size();i<siz;++i)
write(ans3[i]),putchar(i==siz-1?'\n':' ');
}
}
flush();
return 0;
}
「题解」NWRRC2017 Grand Test的更多相关文章
- 「题解」NWRRC2017 Joker
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7028.gym101612J. 题意概述 有一个长度为 \(n\) 的数列,第 \(i\) 个元素的值为 \(a ...
- 「题解」「美团 CodeM 资格赛」跳格子
目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...
- 「题解」「HNOI2013」切糕
文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...
- 「题解」JOIOI 王国
「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...
- 「题解」:[loj2763][JOI2013]现代豪宅
问题 A: 现代豪宅 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...
- 「题解」:$Six$
问题 A: Six 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...
- 「题解」:$Smooth$
问题 A: Smooth 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...
- 「题解」:Kill
问题 A: Kill 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...
- 「题解」:y
问题 B: y 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...
随机推荐
- 【axios】get/post请求params/data传参总结
axios中get/post请求方式 1. 前言 最近突然发现post请求可以使用params方式传值,然后想总结一下其中的用法. 2.1 分类 get请求中没有data传值方式 2.2 get请求 ...
- dubbo服务暴露原理
1.发布流程 暴露本地服务 暴露远程服务 启动netty 连接zookeeper 到zookeeper注册 监听zookeeper 2.官方文档 3.看输出日志,就会发现在暴露本地服务之前,有一句很重 ...
- layui中select的change事件、动态追加option
说明:layui中用jquery 中的选择器例如$('#id').change(function(){})发现不起作用 layui操作:lay-felter标识操作哪个select html部分: & ...
- MindSpore模型验证
技术背景 在前面一篇博客中,我们介绍了MindSpore在机器学习过程中保存和加载模型的方法.这种将模型存储为静态文件的做法,使得我们可以更灵活的使用训练出来的模型,比如用于各种数据集的验证,或者是迁 ...
- 03.14 ICPC训练联盟周赛,Preliminaries for Benelux Algorithm Programming Contest 2019
A .Architecture 题意:其实就是想让你找到两行数的最大值,然后比较是否相同,如果相同输出'possible',不同则输出'impossible' 思路:直接遍历寻找最大值,然后比较即可 ...
- BUAA软件工程个人项目
写在前面 项目 内容 所属课程 2020春季计算机学院软件工程(罗杰 任健) (北航) 作业要求 [个人项目作业](<https://edu.cnblogs.com/campus/buaa/BU ...
- DOM 绑定事件
// 1.获取事件源 var oDiv = document.getElementById('box'); console.log(oDiv); //2.事件 (1)直接绑定匿名函数 oDiv.onc ...
- shell初学之PHP
初次接触脚本,写了一个通过Apache实现PHP动态网站的脚本: #!/bin/bash yum -y install php rm -rf /etc/httpd/conf.d/welcome.con ...
- linux服务之FTP服务篇
一.FTP协议 FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP (File Transfer ...
- 11.7 iostat: I/O信息统计
iostat是I/O statistics(输入/输出统计)的缩写,其主要功能是对系统的磁盘I/O操作进行监视.它的输出主要是显示磁盘读写操作的统计信息,同时也会给出CPU的使用情况.同vmstat命 ...