本文将同步发布于:

题目

题目链接:洛谷 P7025gym101612G

题意概述

给你一张有 \(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的更多相关文章

  1. 「题解」NWRRC2017 Joker

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7028.gym101612J. 题意概述 有一个长度为 \(n\) 的数列,第 \(i\) 个元素的值为 \(a ...

  2. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

  3. 「题解」「HNOI2013」切糕

    文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...

  4. 「题解」JOIOI 王国

    「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...

  5. 「题解」:[loj2763][JOI2013]现代豪宅

    问题 A: 现代豪宅 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...

  6. 「题解」:$Six$

    问题 A: Six 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...

  7. 「题解」:$Smooth$

    问题 A: Smooth 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...

  8. 「题解」:Kill

    问题 A: Kill 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...

  9. 「题解」:y

    问题 B: y 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...

随机推荐

  1. CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析

    0x01 蜘蛛漏洞攻击包 前言:2012 年 2月,地下黑产中流行着一款国产名为蜘蛛漏洞的攻击包 -- "Zhi-Zhu Exploit Pack",该工具包含 5 个漏洞,都是在 ...

  2. CreateThread 线程操作与 _beginthreadex 线程安全(Windows核心编程)

    0x01 线程的创建 线程不同于进程,Windows 中的进程是拥有 '惰性' 的,本身并不执行任何代码,而执行代码的任务转交给主线程,列如使用 CreateProcess 创建一个进程打开 Cmd ...

  3. PowerShell-4.API调用以及DLL调用

    PowerShell可以直接调用API,So...这东西完全和cmd不是一回事了... 调用API的时候几乎和C#一样(注意堆栈平衡): 调用MessageBox: $iii = Add-Type - ...

  4. JAVA教程 Java学习路线

  5. Instagram 为什么不用redis

    Hi 我还是大粽子 碎碎念 让我比较兴奋的就是这段时间的文章,被感兴趣的同学一一关注,关注量上涨就是我的最大动力. 我每周都会输出至少3篇原创文章,希望能被更多的同学关注,点赞,在看,形成习惯. In ...

  6. Django(2)python虚拟环境virtualenvwrapper

    python虚拟环境 虚拟环境(virtual environment),它是一个虚拟化,从电脑独立开辟出来的环境.通俗的来讲,虚拟环境就是借助虚拟机来把一部分内容独立出来,我们把这部分独立出来的东西 ...

  7. 一个入门级CTF的Reverse

    这道题是XCTF攻防世界上的一道新手入门题目! 年前刚接触逆向时IDA,OD了这些工具都不会用(负基础),当时做这些题的时候觉得挺难(主要是缺少练习,没思路无从下手).现在回头再来看这些题目感觉确实是 ...

  8. MySQL5.7升级到8.0过程详解

    前言: 不知不觉,MySQL8.0已经发布好多个GA小版本了.目前互联网上也有很多关于MySQL8.0的内容了,MySQL8.0版本基本已到稳定期,相信很多小伙伴已经在接触8.0了.本篇文章主要介绍从 ...

  9. 设置vue全局配置

    全局配置 创建全局配置文件 vue.config.js 添加配置项

  10. [DB] 关系型数据库

    名词 数据库(database):保存有组织的数据的容器,是通过DBMS创建的容器 表(table):某种特定类型数据的结构化清单 元组(tuple):行,一条数据库记录,对应一个事物 属性(prop ...