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. C#之调用存储过程

    C#调用存储过程   以下内容可能有错漏之处,请大家多多指教. C#后台代码如下: //调用存储过程的方法public static void Startupworkflow(string first ...

  2. 管理mysql数据严格模式,和安全模式处理

    最近使用mysql数据库高一点的版本遇到了,插入和修改等语句失败情况.语句没有错误,但是workbench提示 Field 'id' doesn't have a default value.原因是 ...

  3. python--6、常用模块

    time与datetime模块 time模块,用于输出时间 在Python中,用这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按 ...

  4. 【Linux】tmpfs简介及增加方式

    一. 什么是tmpfs? tmpfs是一种基于内存的文件系统,它和虚拟磁盘ramdisk比较类似,但不完全相同,和ramdisk一样,tmpfs可以使用RAM,但它也可以使用swap分区来存储.而且传 ...

  5. Mysql正则

    摘自:http://www.runoob.com/mysql/mysql-regexp.html 模式 描述 ^ 匹配输入字符串的开始位置.如果设置了 RegExp 对象的 Multiline 属性, ...

  6. X509 颁发者和使用者 详解

    CN=公用名称C=国家ST=省份L =城市或者区域O=组织名称OU=组织单位名称

  7. BZOJ 4259: 残缺的字符串 FFT_多项式

    Code: #include<bits/stdc++.h> #define maxn 1200000 using namespace std; void setIO(string s) { ...

  8. hadoop fs 常用命令(1)

    Hadoop: https://blog.csdn.net/mulangren1988/article/details/54860924 Hadoop:1. Hadoop fs –fs [local ...

  9. 【剑指Offer】 24、二叉树中和为某一值的路径

      题目描述:   输入一颗二叉树的根结点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中, ...

  10. 数据挖掘系列 (1) 关联规则挖掘基本概念与 Aprior 算法

    转自:http://www.cnblogs.com/fengfenggirl/p/associate_apriori.html 数据挖掘系列 (1) 关联规则挖掘基本概念与 Aprior 算法 我计划 ...