洛谷3388 tarjan割点
题目链接:https://www.luogu.com.cn/problem/P3388
tarjan算法果然牛逼,时间复杂度是O(|V|+|E|),所以1e4个结点2e5条边的图完全不在话下orz orz
一个无向图求割点,该图不一定连通,所以要对没有访问过的点继续tarjan,这时候我就wa了几次,因为之前只用过一次tarjan,在参数设置里面我默认了从u=1开始建dfs树。每次只有根节点的father值等于其编号,这样就能唯一地标识它,学到了。其次在下面证明 tarjan中如果在处理回退边的时候用的是①、 low[u]=min(low[u],low[v])(强连通分量的用法)而不是②、low[u]=min(low[u],dfn[v])的话将会出现什么样的错误。

我们模拟两种Tarjan算法,一种是low[u] = min( low[u], low[v] );,一种是low[u] = min( low[u], dfn[v] );。(证明参考洛谷博客)
第1种:
① dfs(1),dfn[1] = 1,low[1] = 1。
② dfs(2),dfn[2] = 2,low[2] = 2。
③ dfs(3),dfn[3] = 3,low[3] = 3。
④ 发现回边 3 -> 1,low[3] = 1。
⑤ dfs(4),dfn[4] = 4,low[4] = 4。
⑥ dfs(5),dfn[5] = 5,low[5] = 5。
⑦ 发现回边 5 -> 3,low[5] = 1。
⑧ dfs(5)结束,回到dfs(4),low[4] = 1。
⑨ dfs(4)结束,回到dfs(3),low[3] = 1。
⑩ dfs(3)结束,至此未发现割点。
第2种:
① dfs(1),dfn[1] = 1,low[1] = 1。
② dfs(2),dfn[2] = 2,low[2] = 2。
③ dfs(3),dfn[3] = 3,low[3] = 3。
④ 发现回边 3 -> 1,low[3] = 1。
⑤ dfs(4),dfn[4] = 4,low[4] = 4。
⑥ dfs(5),dfn[5] = 5,low[5] = 5。
⑦ 发现回边 5 -> 3,low[5] = 3。
⑧ dfs(5)结束,回到dfs(4),low[4] = 3。
⑨ dfs(4)结束,回到dfs(3),low[4] >= dfn[3],发现割点3,low[3] = 1。
而这个图中,正确答案是:3是割点。
所以第1种方法就被我们愉快地Hack掉了。
其次,我在处理回退边的时候在条件中加上了dfn[v]<dfn[u],时间效率提高了大约10%,这是显而易见的,因为只有回退边到达的结点在父节点之前被访问,而且这个结点还不是已经处理过的fa结点。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a))
#define prime1 1e9+7
#define prime2 1e9+9
#define pi 3.14159265
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define scand(x) scanf("%llf",&x)
#define f(i,a,b) for(int i=a;i<=b;i++)
#define scan(a) scanf("%d",&a)
#define mp(a,b) make_pair((a),(b))
#define P pair<int,int>
#define dbg(args) cout<<#args<<":"<<args<<endl;
#define inf 0x3f3f3f3f
const int maxn=2e4+;
int n,m,t;
inline int read(){
int ans=,w=;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-;ch=getchar();}
while(isdigit(ch))ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
return ans*w;
}
int low[maxn],dfn[maxn],iscut[maxn],head[maxn],nxt[];
int cnt=;
int ans=;
struct node{
int u,v;
}p[];
int e=;
void addedge(int x,int y)
{
p[e].u=x;
p[e].v=y;
nxt[e]=head[x];
head[x]=e++;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;
int child=;
for(int i=head[u];~i;i=nxt[i])
{
int v=p[i].v;
if(!dfn[v])
{
if(fa==u)child++;
tarjan(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u]&&u!=fa)iscut[u]=;
}
else if(dfn[v]<dfn[u]&&v!=fa)
{
low[u]=min(low[u],dfn[v]);
}
}
if(u==fa&&child>)iscut[u]=;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
std::ios::sync_with_stdio(false);
n=read(),m=read();
int x,y;
cnt=;
ans=;
mem(low,);
mem(dfn,);
mem(iscut,);
mem(head,-);
mem(nxt,-);
f(i,,m)
{
x=read(),y=read();
addedge(x,y);
addedge(y,x);
}
f(i,,n)
{
if(!dfn[i])tarjan(i,i);//图不一定连通,所以每个连通分量都要tarjan一次
}
f(i,,n)
{
if(iscut[i])ans++;
}
pf("%d\n",ans);
f(i,,n)
if(iscut[i])pf("%d ",i);
return ;
}
洛谷3388 tarjan割点的更多相关文章
- 洛谷3388 【模板】割点 tarjan算法
题目描述 给出一个n个点,m条边的无向图,求图的割点. 关于割点 在无向连通图中,如果将其中一个点以及所有连接该点的边去掉,图就不再连通,那么这个点就叫做割点(cut vertex / articul ...
- NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
原文链接https://www.cnblogs.com/zhouzhendong/p/9258043.html 题目传送门 - 洛谷P3953 题目传送门 - Vijos P2030 题意 给定一个有 ...
- 洛谷 - P3469 - BLO-Blockade - 割点
https://www.luogu.org/problem/P3469 翻译:一个原本连通的无向图,可以删除图中的一个点,求因为删除这个点所导致的不连通的有序点对的数量.或者说,删去这个点之后,各个连 ...
- 【Tarjan】洛谷P3379 Tarjan求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 洛谷P1073 Tarjan + 拓扑排序 // 构造分层图
https://www.luogu.org/problemnew/show/P1073 C国有 n n个大城市和 mm 条道路,每条道路连接这 nn个城市中的某两个城市.任意两个城市之间最多只有一条道 ...
- 「洛谷3469」「POI2008」BLO-Blockade【Tarjan求割点】
题目链接 [洛谷传送门] 题解 很显然,当这个点不是割点的时候,答案是\(2*(n-1)\) 如果这个点是割点,那么答案就是两两被分开的联通分量之间求组合数. 代码 #include <bits ...
- ⌈洛谷5058⌋⌈ZJOI2004⌋嗅探器【Tarjan】
题目连接 [洛谷传送门] [LOJ传送门] 题目描述 某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心 ...
- tarjan算法比较详细的讲解&&tarjan常见疑难解答&&洛谷P2002 消息扩散题解
因为有大佬写的比我更长更具体,所以我也就写写总结一下了 引入: 众所周知,很多图中有个东西名叫环. 对于这个东西很多算法都很头疼.(suchas 迪杰斯特拉) 更深层:环属于强联通分量(strongl ...
- 洛谷 P2194 HXY烧情侣【Tarjan缩点】 分析+题解代码
洛谷 P2194 HXY烧情侣[Tarjan缩点] 分析+题解代码 题目描述: 众所周知,HXY已经加入了FFF团.现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了.这里 ...
随机推荐
- linux查看端口号占用命令-netstat
题记 经常会发现,很多时候我们在运行一些带有端口的程序时,程序经常会报端口被占用的问题,比如Tomcat 8080,端口起不来. 查看端口号 netstat 如果发现某个端口被占用后,可以用命令查看, ...
- Python如何规避全局解释器锁(GIL)带来的限制
编程语言分类概念介绍(编译型语言.解释型语言.静态类型语言.动态类型语言概念与区别) https://www.cnblogs.com/zhoug2020/p/5972262.html Python解释 ...
- 测试用例设计经典面试题之电梯、杯子、笔、桌子、洗衣机、椅子、ATM等
测试用例设计经典面试题之电梯.杯子.笔.桌子.洗衣机.椅子.ATM等 1.测试项目:电梯 需求测试:查看电梯使用说明书.安全说明书等 界面测试:查看电梯外观 功能测试:测试电梯能否实现正常的上升和下降 ...
- ES介绍与实践
一.ES介绍 1.基础概念介绍 1. 索引:Elasticsearch中的“索引”有点像关系数据库中的数据库. 它是存储/索引数据的地方: 2.分片 shard “分片”是Lucene的一个索引. 它 ...
- 听起来很美,用起来很累!停车类APP软肋在哪
据数据显示,全国现有汽车已达1亿7千万辆,停车位缺于6800万个.而在北京,汽车保有量和车位的配比大约是1:0.5,而国际上一般是1:1.2,结构严重失衡.正所谓哪里有需求,哪里就有市场.停车位的走俏 ...
- Ubuntu 14.04 下NFS安装配置
1.执行命令:sudo apt-get install nfs-kernel-server; 2.执行命令:mkdir /home/jack/nfs-share 建立一个nfs服务的专有的文件夹; 3 ...
- 沈向洋|微软携手 OpenAI 进一步履行普及且全民化人工智能的使命
OpenAI 进一步履行普及且全民化人工智能的使命"> 作者简介 沈向洋,微软全球执行副总裁,微软人工智能及微软研究事业部负责人 我们正处于技术发展历程中的关键时刻. 云计算的强大计算 ...
- C++走向远洋——34(友元函数,成员函数和一般函数的区别)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:youyuan.cpp * 作者:常轩 * 微信公众号:Worl ...
- 机器学习基础——详解自然语言处理之tf-idf
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天的文章和大家聊聊文本分析当中的一个简单但又大名鼎鼎的算法--TF-idf.说起来这个算法是自然语言处理领域的重要算法,但是因为它太有名了 ...
- Java并发编程(01):线程的创建方式,状态周期管理
本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...