前排Orz tarjan

tarjan算法在图的连通性方面有非常多的应用,dfn和low数组真是奥妙重重(并没有很搞懂反正背就完事了)

有向图强连通分量

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std;
struct edge{
int v,next;
}a[];
stack<int>s;
int n,m,u,v,sum=,tt=-,ans=,h[],anss[],num[],nums[],tot=,tim=,dfn[],low[],head[];
bool used[],isin[];
void tarjan(int u){
int v;
used[u]=isin[u]=true;
low[u]=dfn[u]=++tim;
s.push(u);
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(!used[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else{
if(isin[v])low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
v=-;
sum++;
while(v!=u){
v=s.top();
s.pop();
isin[v]=;
num[v]=sum;
nums[sum]++;
}
}
}
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
int main(){
memset(used,,sizeof(used));
memset(head,-,sizeof(head));
memset(h,-,sizeof(h));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=;i<=n;i++){
if(!used[i])tarjan(i);
}
tot=;
for(int i=;i<=n;i++){
for(int tmp=head[i];tmp!=-;tmp=a[tmp].next){
if(num[i]!=num[a[tmp].v]){
h[num[i]]=++tot;
}
}
}
for(int i=;i<=sum;i++){
if(nums[i]>)ans++;
}
printf("%d\n",ans);
for(int i=;i<=sum;i++){
if(h[i]==-){
if(tt!=-||nums[i]==){
tt=-;
break;
}else tt=i;
}
}
if(tt==-)printf("-1");
else for(int i=;i<=n;i++){
if(num[i]==tt)printf("%d ",i);
}
return ;
}

无向图割点

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge{
int v,next;
}a[];
int t=,n,s,ss,u,v,tim=,sum=,tot=,head[],dfn[],low[];
bool f=false,used[],ff[];
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void tarjan(int u,int fa){
int v;
dfn[u]=low[u]=++tim;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(!low[v]){
tarjan(v,u);
if(u==)sum++;
low[u]=min(low[u],low[v]);
if(u!=&&dfn[u]<=low[v]){
ff[u]=true;
}
}else if(v!=fa){
low[u]=min(low[u],dfn[v]);
}
}
}
void dfs(int u){
int v;
used[u]=true;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(!used[v])dfs(v);
}
}
int main(){
while(scanf("%d",&s)&&s){
printf("Network #%d\n",++t);
memset(head,-,sizeof(head));
memset(ff,,sizeof(ff));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
tot=n=sum=tim=;
f=false;
scanf("%d",&ss);
add(s,ss);
add(ss,s);
n=max(n,max(s,ss));
scanf("%d",&s);
while(s){
scanf("%d",&ss);
add(s,ss);
add(ss,s);
n=max(n,max(s,ss));
scanf("%d",&s);
}
tarjan(,-);
if(sum>)ff[]=true;
for(int i=;i<=n;i++){
if(ff[i]){
memset(used,,sizeof(used));
f=used[i]=true;
sum=;
for(int j=;j<=n;j++){
if(!used[j]){
sum++;
dfs(j);
}
}
printf(" SPF node %d leaves %d subnets\n",i,sum);
}
}
if(!f){
printf(" No SPF nodes\n");
}
printf("\n");
}
return ;
}
/*
1 2
5 4
3 1
3 2
3 4
3 5
0 1 2
2 3
3 4
4 5
5 1
0 1 2
2 3
3 4
4 6
6 3
2 5
5 1
0 0
--------
Network #1
SPF node 3 leaves 2 subnets Network #2
No SPF nodes Network #3
SPF node 2 leaves 2 subnets
SPF node 3 leaves 2 subnets
*/

无向图点双连通分量

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<stack>
using namespace std;
struct edge{
int v,next;
}a[];
struct edge1{
int u,v;
};
int n,m,u,v,tot=,tim=,bcctot=,bccnum[],head[],dfn[],low[],iscut[];
vector<int>ans[];
stack<edge1>s;
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void tarjan(int u,int fa){
edge1 t;
int v,son;
dfn[u]=low[u]=++tim;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(v==fa)continue;
t.u=u;
t.v=v;
if(!dfn[v]){
s.push(t);
son++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
iscut[u]=true;
ans[++bcctot].clear();
while(true){
edge1 tt=s.top();
s.pop();
if(bccnum[tt.u]!=bcctot){
ans[bcctot].push_back(tt.u);
bccnum[tt.u]=bcctot;
}
if(bccnum[tt.v]!=bcctot){
ans[bcctot].push_back(tt.v);
bccnum[tt.v]=bcctot;
}
if(tt.u==u&&tt.v==v)break;
}
}
}else if(dfn[v]<low[u]){
s.push(t);
low[u]=min(low[u],dfn[v]);
}
}
if(fa<&&son==)iscut[u]=false;
}
int main(){
memset(iscut,,sizeof(iscut));
memset(head,-,sizeof(head));
memset(low,,sizeof(low));
memset(bccnum,,sizeof(bccnum));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
tarjan(,-);
for(int i=;i<=bcctot;i++){
printf("%d:",i);
for(int j=;j<ans[i].size();j++){
printf("%d ",ans[i][j]);
}
printf("\n");
}
return ;
}
/*
6 7
1 2
2 3
1 3
3 4
4 5
3 5
5 6
--------
1:5 6
2:4 3 5
3:2 1 3
*/

无向图求桥

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge{
int u,v,next;
}a[];
int n,m,u,v,tot=,tim=,head[],dfn[],low[],ansu[],ansv[];
void add(int u,int v){
a[++tot].u=u;
a[tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void tarjan(int u,int fa){
int v;
dfn[u]=low[u]=++tim;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(dfn[v]==){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
ansu[++ansu[]]=u;
ansv[++ansv[]]=v;
}
}else{
if(dfn[v]<dfn[u]&&v!=fa){
low[u]=min(low[u],dfn[v]);
}
}
}
}
int main(){
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
ansu[]=;
ansv[]=;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
tarjan(,-);
printf("--------\n");
for(int i=;i<=ansv[];i++){
printf("%d %d\n",ansu[i],ansv[i]);
}
return ;
}
/*
6 7
1 2
2 3
1 3
3 4
4 5
5 6
6 4
--------
3 4
*/

无向图边双连通分量

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
struct edge{
int v,next;
}a[];
int n,m,u,v,tot=,tim=,num=,head[],dfn[],low[],bl[];
bool used[],bri[];
vector<int>g[];
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void tarjan(int u,int fa){
int v;
dfn[u]=low[u]=++tim;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
v=a[tmp].v;
if(dfn[v]==){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
bri[tmp]=true;
bri[tmp^]=true;
}
}else{
if(dfn[v]<dfn[u]&&v!=fa){
low[u]=min(low[u],dfn[v]);
}
}
}
}
void dfs(int u){
used[u]=true;
bl[u]=num;
g[num].push_back(u);
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(bri[tmp])continue;
if(!used[v])dfs(v);
}
}
int main(){
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(used,,sizeof(used));
memset(bri,,sizeof(bri));
memset(bl,,sizeof(bl));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i=;i<=n;i++){
if(!dfn[i])tarjan(i,-);
}
for(int i=;i<=n;i++){
if(!used[i]){
num++;
dfs(i);
}
}
for(int i=;i<=num;i++){
printf("%d: ",i);
for(int j=;j<g[i].size();j++)printf("%d ",g[i][j]);
printf("\n");
}
return ;
}

Tarjan专题的更多相关文章

  1. 【noip暑假tarjan专题】

    %%%奎老师 A:傻逼缩点...傻逼编译器卡我next... B:就是这道奎老师没讲清楚的题,明明小朋友们都一A嘛,,,明明细节有很多嘛,,,怎么都这么熟练啊. C:本质还是B,换了个马甲而已. D: ...

  2. 校际联合Contest

    每次开一个坑都像是重新被碾压的预感 最近的新闻,以前很喜欢乔任梁的<复活>...然后他就死了...感觉我再多愁善感一点的话...就要悲伤逆流成河了吧... Contest 09/24(乐滋 ...

  3. 连通图(Tarjan算法) 专题总结

    一.题目类型: 1.有向图的强连通分量: POJ1236 Network of Schools HDU1269 迷宫城堡 2.割点 & 割边: UESTC - 900 方老师炸弹 UVA315 ...

  4. tarjan 题目汇总(含解析)

    下面容许我偷个懒,洛谷上写过的blog我就不来再抄一遍了 洛谷P3436 [[POI2006]PRO-Professor Szu](别称:作死的老教授) 洛谷P4306 [[JSOI2010]连通数] ...

  5. POJ 1470 Closest Common Ancestors (LCA,离线Tarjan算法)

    Closest Common Ancestors Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 13372   Accept ...

  6. Tarjan 算法求 LCA / Tarjan 算法求强连通分量

    [时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...

  7. NOIp 图论算法专题总结 (2)

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 树链剖分 https://oi-wiki.org/graph/heavy-lig ...

  8. 20行代码实现,使用Tarjan算法求解强连通分量

    今天是算法数据结构专题的第36篇文章,我们一起来继续聊聊强连通分量分解的算法. 在上一篇文章当中我们分享了强连通分量分解的一个经典算法Kosaraju算法,它的核心原理是通过将图翻转,以及两次递归来实 ...

  9. DFS序专题

    牛客专题之DFS序 简介 dfs序: 每个节点在dfs深度优先遍历中的进出栈的时间序列,也就是tarjan算法中的dfn数组. 画个图理解一下: 这棵树的dfs序:1 3 2 4 2 5 6 7 6 ...

随机推荐

  1. MySQL_索引原理与慢查询优化

    索引原理与慢查询优化 创建/删除索引的语法 #方法一:创建表时 CREATE TABLE 表名 ( 字段名1 数据类型 [完整性约束条件…], 字段名2 数据类型 [完整性约束条件…], [UNIQU ...

  2. [读书笔记] Python数据分析 (一) 准备工作

    1. python中数据结构:矩阵,数组,数据框,通过关键列相互联系的多个表(SQL主键,外键),时间序列 2. python 解释型语言,程序员时间和CPU时间衡量,高频交易系统 3. 全局解释器锁 ...

  3. oracle数据库服务介绍

    共有7个服务,这七个服务的含义分别为: 1. Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Service ...

  4. 20130910.Windows上安装和配置MongoDB

    官方文档:http://docs.mongodb.org/manual/tutorial/ 1.下载软件 http://www.mongodb.org/downloads 2.解压 解压后进入bin目 ...

  5. HDU 4253 Two Famous Companies

    Two Famous Companies Time Limit: 15000ms Memory Limit: 32768KB This problem will be judged on HDU. O ...

  6. Nutch的配置(使用MySQL作为数据存储)

    首先先从http://www.apache.org/dyn/closer.cgi/nutch/下载安装包 这里假定nutch的根目录为:${APACHE_NUTCH_HOME} 配置${APACHE_ ...

  7. Spring注解+Axis2开发WebService

    用Spring注解方式: 配置扫描指定包下的类 <context:component-scan base-package="包名" />   标识类为spring管理的 ...

  8. HDU 2421

    由算术基本定理N=p1^e1*p2^e2....ps^es,可知一个素的因子个数为(e1+1)*(e2+1)*...*(es+1). 而N的一人因子必定也有n=p1^k1*p2^k2....*ps^k ...

  9. POJ 3904

    第一道莫比乌斯反演的题. 建议参看http://www.isnowfy.com/mobius-inversion/ 摘其中部分 证明的话感觉写起来会比较诡异,大家意会吧说一下这个经典题目:令R(M,N ...

  10. 为什么选性别会导致兴趣都选中-vue

    为什么选性别会导致兴趣都选中-vue <%@ page language="java" import="java.util.*" pageEncoding ...