0x66 Tarjan算法与无向图联通性
poj3694 先e-DCC缩点,此时图就变成了树,树上每一条边都是桥。对于添加边的操作,相当于和树上一条路径构环,导致该路径上所有边都不成为桥。那么找这条新加边的最近公共祖先,把路径上的所有没被删掉的桥的数量计算出来,未操作之前桥的个数减去该值就是当前答案。中间因为一条边会多次删除,没有意义,可以采取并查集路径压缩的思想,直接指向下一个没有被删的桥
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int z,dfn[],low[];
bool b[];
void tarjan(int x,int fr)
{
dfn[x]=low[x]=++z;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==)
{
tarjan(y,x);
low[x]=min(low[x],low[y]); if(dfn[x]<low[y])
b[k]=b[k^]=true;
}
if(y!=fr)
low[x]=min(low[x],dfn[y]);
}
}
int cnt,bel[];
void sdfj(int x,int fr)
{
bel[x]=cnt;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(bel[y]==&&b[k]==false)
sdfj(y,x);
}
} //--------------------缩点---------------------- int Bin[];
int f[][],dep[];
void dfs(int x)
{
for(int i=;dep[x]>=Bin[i];i++)f[i][x]=f[i-][f[i-][x]]; for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=f[][x])
{
f[][y]=x;
dep[y]=dep[x]+;
dfs(y);
}
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)
if(dep[x]-dep[y]>=Bin[i])x=f[i][x];
if(x==y)return x;
for(int i=;i>=;i--)
if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
return f[][x];
} //--------------get_LCA---------------------------- int fa[];bool v[];
int main()
{
int n,m,T_T=;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==&&m==)break; printf("Case %d:\n",++T_T);
len=;memset(last,,sizeof(last));
int x,y;
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
z=;
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(b,false,sizeof(b));
tarjan(,); cnt=;
memset(bel,,sizeof(bel));
for(int i=;i<=n;i++)
if(bel[i]==) cnt++, sdfj(i,);
int tp=;
memset(last,,sizeof(last));
for(int i=;i<=len;i++)
{
if(bel[a[i].x]!=bel[a[i].y])
{
tp++;
a[tp].x=bel[a[i].x];
a[tp].y=bel[a[i].y];
a[tp].next=last[a[tp].x];
last[a[tp].x]=tp;
}
}
len=tp; Bin[]=;for(int i=;i<=;i++)Bin[i]=Bin[i-]*;
f[][]=;dep[]=;dfs(); for(int i=;i<=cnt;i++)fa[i]=f[][i];
memset(v,false,sizeof(v));
int Q,ans=cnt-;
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&x,&y);x=bel[x],y=bel[y];
int lca=LCA(x,y),t;
while(dep[x]>dep[lca])
{
if(v[x]==false){ans--;v[x]=true;}
t=fa[x];
if(dep[fa[x]]<dep[lca])fa[x]=lca;
x=t;
}
while(dep[y]>dep[lca])
{
if(v[y]==false){ans--;v[y]=true;}
t=fa[y];
if(dep[fa[y]]<dep[lca])fa[y]=lca;
y=t;
}
printf("%d\n",ans);
}
printf("\n");
}
return ;
}
poj3694
poj2942 建补图,也就是可以坐在一起的连边。对于一次会议,上面坐着的骑士在图中就是一个简单环,所以这道题其实就是找那些没有在任何奇环中的点。找出所有的v-DCC,用黑白染色判即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
} int tim,ti[];
bool col[],v[];
bool findodd(int x)
{
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(ti[y]==tim)
{
if(v[y]==false)
{
v[y]=true;
col[y]=col[x]^;
if(findodd(y))return true;
}
else if(col[y]==col[x])return true;
}
}
return false;
}
int z,dfn[],low[];
int top,sta[],hlen,h[]; bool inodd[];
void v_DCC(int x,int fr)
{
dfn[x]=low[x]=++z;sta[++top]=x;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==)
{
v_DCC(y,x);
low[x]=min(low[x],low[y]);
if(dfn[x]<=low[y])
{
int k;tim++;hlen=;
do
{
k=sta[top];top--;
h[++hlen]=k;
ti[k]=tim;v[k]=false;
}while(k!=y); if(dfn[x]==low[y])
{
h[++hlen]=x;
ti[x]=tim;v[x]=false;
}
col[y]=;
if(findodd(y))
{
for(int i=;i<=hlen;i++)
inodd[h[i]]=true;
}
}
}
else if(y!=fr)
low[x]=min(low[x],dfn[y]);
}
} bool mp[][];
int main()
{
int n,m,x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==&&m==)break; memset(mp,true,sizeof(mp));
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
mp[x][y]=mp[y][x]=false;
}
len=;memset(last,,sizeof(last));
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(i!=j&&mp[i][j]==true)ins(i,j); z=;top=;tim=;
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(inodd,false,sizeof(inodd));
memset(ti,,sizeof(ti));
for(int i=;i<=n;i++)
if(dfn[i]==)v_DCC(i,); int ans=;
for(int i=;i<=n;i++)
if(inodd[i]==false)ans++;
printf("%d\n",ans);
}
return ;
}
poj2942
poj2230 欧拉回路裸题。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
} int top,sta[],cur[]; bool v[];
int aslen,as[];
void euler()
{
top=;sta[++top]=;
memset(v,false,sizeof(v));
memcpy(cur,last,sizeof(cur));
while(top!=)
{
int x=sta[top],k;
for(k=cur[x];k&&v[k];k=a[k].next);
if(k)
{
sta[++top]=a[k].y;
v[k]=true;
cur[x]=a[k].next;
}
else top--,as[++aslen]=x;
}
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
len=;memset(last,,sizeof(last));
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
euler();
for(int i=aslen;i>=;i--)printf("%d\n",as[i]);
return ;
}
poj2230
0x66 Tarjan算法与无向图联通性的更多相关文章
- 0x66 Tarjan算法与无向图连通性(1)
……是什么? 给定无向连通图G=(V,E)(不一定连通); 割点:若对于x∈V,从图中删去节点x以及所有与x关联的边后,G分裂成两个或两个以上不相连的子图,则称x为G的割点. 桥(割边):若对于e∈E ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
- tarjan算法求无向图的桥、边双连通分量并缩点
// tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...
- tarjan算法--求无向图的割点和桥
一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...
- tarjan算法--求解无向图的割点和桥
1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥 也就是说 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥 2.割点:无向连通图中,如 ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...
- Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释
原题链接 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...
- [Tarjan系列] Tarjan算法求无向图的桥和割点
RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...
- SPF Tarjan算法求无向图割点(关节点)入门题
SPF 题目抽象,给出一个连通图的一些边,求关节点.以及每个关节点分出的连通分量的个数 邻接矩阵只要16ms,而邻接表却要32ms, 花费了大量的时间在加边上. // time 16ms 1 ...
随机推荐
- 利用windbg获取dump的dll文件
根据堆栈对应的地址查找其对应的Module ID,然后将对应的Module保存. !IP2MD 命令从托管函数中获取 MethodDesc 结构地址. !dumpmodule 1caa50 下面的命令 ...
- dubbo之本地调用
本地调用 本地调用使用了 injvm 协议,是一个伪协议,它不开启端口,不发起远程调用,只在 JVM 内直接关联,但执行 Dubbo 的 Filter 链. 配置 定义 injvm 协议 <du ...
- Cell期刊论文:为什么计算机人脸识别注定超越人类?(祖母论与还原论之争)
终于找到ML日报的微信链接,抄之...................................... 请拜访原文链接:[祖母论与还原论之争]为什么计算机人脸识别注定超越人类?评价: ...
- element-ui按需引入
{ "name": "vue-test2", "description": "A Vue.js project", &q ...
- BZOJ 1426: 收集邮票 数学期望 + DP
Description 有n种不同的邮票,皮皮想收集所有种类的邮票.唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且 买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n.但是由于凡凡 ...
- maven将jar包添加到本地仓库
mvn install:install-file -Dfile=jar包本地路径 -DgroupId=groupID -DartifactId=ifactId -Dversion=版本 -Dpacka ...
- 解析python部分常用魔术方法
def __add__(self, *args, **kwargs): # real signature unknown """ Return self+value. & ...
- ext4的一些特性
delalloc介绍 delalloc是ext4下的一个新特性,延迟分配技术Delay Allocation. 实现原理为: Buffer Write时数据会被保存到page cache中,但是系统并 ...
- Linux—Ubuntu14.0.5设置MySQL的字符集
1.mysql配置文件地址 cd /etc/mysql/my.cnf 2.在[mysqld]在下方添加以下代码 [mysqld] init_connect='SET collation_connect ...
- PAT 1075. PAT Judge
The ranklist of PAT is generated from the status list, which shows the scores of the submittions. Th ...