bzoj1123: [POI2008]BLO

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算法与无向图联通性的更多相关文章

  1. 0x66 Tarjan算法与无向图连通性(1)

    ……是什么? 给定无向连通图G=(V,E)(不一定连通); 割点:若对于x∈V,从图中删去节点x以及所有与x关联的边后,G分裂成两个或两个以上不相连的子图,则称x为G的割点. 桥(割边):若对于e∈E ...

  2. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

  3. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  4. tarjan算法--求无向图的割点和桥

    一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...

  5. tarjan算法--求解无向图的割点和桥

    1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥 也就是说 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥 2.割点:无向连通图中,如 ...

  6. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

  7. Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

     原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...

  8. [Tarjan系列] Tarjan算法求无向图的桥和割点

    RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...

  9. SPF Tarjan算法求无向图割点(关节点)入门题

    SPF 题目抽象,给出一个连通图的一些边,求关节点.以及每个关节点分出的连通分量的个数 邻接矩阵只要16ms,而邻接表却要32ms,  花费了大量的时间在加边上. //   time  16ms 1 ...

随机推荐

  1. 好用的Cache辅助工具类

    话不多说,直接上代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...

  2. lsit集合去重复 顶级表达式

    updateList = updateList.Where((x, i) => updateList.FindIndex(z => z.ID == x.ID) == i).ToList() ...

  3. sql--Truncate Table

    Truncate Table(截断表) 有时候需要清除一个表中的所有资料.要达到者个目的,一种方式是DROP TABLE 指令.不过这样整个表格就消失,而无法再被用了. 另一种方式是Delete不带w ...

  4. windows phone数据网络开发

    LINQ LINQ的全称是Language INtegrated Query,即语言集成查询.LINQ是一种查询语言,不仅可以对数字库进行查询,还可以对.net的数据集.数组.Xml文档等对象进行查询 ...

  5. MemcachedClient 使用说明

    上一篇介绍了Memcached基本使用方法<Memcached使用手册>,下面介绍java如何操作memcached.使用的是java_memcached-release_2.6.6. 一 ...

  6. Java数组!!!你知多少?

    这是一篇网上搜到的文章,对数组进行了充分的说明.楼主懂了数组的俩种初始化方式:静态初始化和动态初始化方式.(贴过来备用哦) 下面我带大家一起加深一下对Java数组的认识: 1.理解数组 数组也是一种数 ...

  7. SAP computer之architecture

    Simple-As-Possible computer introduces all the cruicial ideas behind computer operation without bury ...

  8. [转]常用Git命令清单

    原文地址:http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html 作者: 阮一峰 日期: 2015年12月 9日 我每天使用 Git , ...

  9. 学习廖雪峰的Python教程之Python基础

    一.缩进 编译器或者解释器就是负责把符合语法的程序代码转换成CPU能够执行的机器码,然后执行. 以#开头的语句是注释,注释是给人看的,可以是任意内容,解释器会忽略掉注释.其他每一行都是一个语句,当语句 ...

  10. 使用CImage类 显示图片

    在不适用openCv的一种时候,使用CImage显示图片数据,并且直接嵌入DC框中. 使用CImage 在pic控件里显示图片 void CMyCalLawsDlg::MyShowImage( CIm ...