前排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. POJ 1328 Radar Installation 【贪心 区间选点】

    解题思路:给出n个岛屿,n个岛屿的坐标分别为(a1,b1),(a2,b2)-----(an,bn),雷达的覆盖半径为r 求所有的岛屿都被覆盖所需要的最少的雷达数目. 首先将岛屿坐标进行处理,因为雷达的 ...

  2. Unity 动画系统(Mecanim) 术语及翻译 表格

    原文 翻译 Animation Clip 视频片段 Avatar 阿凡达 Retargeting 重定向 Rigging 绑定 skinning 蒙皮 Animator Component 动画组件 ...

  3. NGUI 按钮点击事件的两种绑定形式

    面板属性栏绑定 写一个脚本,定义一个Public的方法 Notify中选择物体时,选中自己 然后就可以选择通知到写的那个脚本的里边的public方法 代码绑定 创建一个代码文件,挂载到按钮对象上 代码 ...

  4. ZBrush软件特性之Color调控板

    ZBrush®中的Color调色板显示当前颜色并提供数值的方法选择颜色,而且选择辅助色,使用描绘工具可以产生混合的色彩效果. ZBrush 4R8下载:http://wm.makeding.com/i ...

  5. 基于cxf的webService服务发布及客户端开发

    学习地址: http://www.cnblogs.com/leihenqianshang/category/795140.html

  6. mysql创建数据库并指定uft8编码

    CREATE DATABASE IF NOT EXISTS ymk default character set utf8 COLLATE utf8_general_ci;

  7. mysql linux查看配置文件my.cnf位置

    原文:mysql linux查看配置文件my.cnf位置 命令: mysql --help | grep 'Default options' -A 1

  8. ES6特性:(阮一峰老师)学习总结

    ES6(阮一峰)学习总结   1.块级作用域的引入 在ES6之前,js只有全局作用域和函数作用域,ES6中let关键字为其引入了块级作用域. { var a = 5; let b = 6; } con ...

  9. tddl

    淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer 外号:头都大了 ?_Ob)框架,主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个 ...

  10. [Angular] Provide Feedback to Progress Events with Angular’s HttpRequest Object

    In some cases your application might need to upload large amounts of data, such as files. Obviously ...