题目链接:https://vjudge.net/problem/POJ-3694

题目:给定一个连通图,求桥的个数,每次查询,加入一条边,问加入这条边后还有多少个桥。

思路:tarjan + 并查集 + lca(朴素)

先用tarjan缩点(成环缩点),并存下桥,把每个scc都存下一个源点(源点(boss):以这个点代表这个scc)。

用存下的桥,用并查集重新建图,为了方便之后的操作,并查集建立一颗树,dfn小的在上,dfn大的在下。

lca,用每个点的boss的dfn去跑lca,因为我们建树的方法,总会遇到公共的dfn祖先,把这些点都存下,

最后把这些boss点的dfn都变成祖先的dfn值,这样优化了重复的lca,之后输出答案即可。

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define pb push_back const int N = (int)5e5+;
int n,m,tot,tim,top,scc,ans;//点,边,链式前向星,时间戳,栈,连通数
int head[N],dfn[N],low[N],scc_no[N],s[N],fa[N],boss[N];
//链式前向星,dfn,low,联通块编号,栈,父节点,源点
struct node{
int to;
int nxt;
}e[N << ];
struct _cut{
int x,y;
};
vector<_cut> cut;//桥
vector<int> poi;//lca void init(){
for(int i = ; i <= n; ++i){
head[i] = -;
dfn[i] = ;
}
cut.clear();
scc = tim = tot = ;
} inline void add(int u,int v){
e[tot].to = v;
e[tot].nxt = head[u];
head[u] = tot++;
} void tarjan(int now,int pre){
dfn[now] = low[now] = ++tim;
s[top++] = now; int to,pre_cnt = ;
for(int o = head[now]; ~o; o = e[o].nxt){
to = e[o].to;
if(to == pre && pre_cnt == ) { pre_cnt = ; continue; }
if(!dfn[to]){
tarjan(to,now);
low[now] = min(low[now],low[to]);
if(dfn[now] < low[to]) cut.pb(_cut{now,to});
}
else if(low[now] > dfn[to]) low[now] = dfn[to];
} if(dfn[now] == low[now]){
int p;
++scc;
fa[now] = now; boss[scc] = now;//记录该scc的源点
do{
p = s[--top];
scc_no[p] = scc;
}while(now != p);
}
}
//得到源点函数
inline int _boss(int x){
return boss[scc_no[x]];
}
//重建图 boss进行并查集
void rebuild(){
ans = cut.size();
int x,y;
for(int i = ; i < ans; ++i){
x = _boss(cut[i].x);
y = _boss(cut[i].y);
//dfn上小,下大的树
if(dfn[x] > dfn[y]) swap(x,y);
fa[y] = x;
}
} void lca(int x,int y){
int fax = _boss(x);
int fay = _boss(y);
if(dfn[fax] == dfn[y]) return; poi.pb(fax); poi.pb(fay);
while(dfn[fax] != dfn[fay]){
while(dfn[fax] > dfn[fay]){
--ans;
fax = fa[fax];
poi.pb(fax);
}
while(dfn[fax] < dfn[fay]){
--ans;
fay = fa[fay];
poi.pb(fay);
}
} int n = poi.size();//所有boss点dfn改变为祖先的dfn
for(int i = ; i < n; ++i) dfn[poi[i]] = dfn[fax];
poi.clear();
} int main(){ int _case = ;
while(~scanf("%d%d",&n,&m) && (n+m)){
init();
int u,v;
for(int i = ; i < m; ++i){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
} tarjan(,);
rebuild(); int q;
scanf("%d",&q);
printf("Case %d:\n",++_case);
while(q--){
scanf("%d%d",&u,&v);
lca(u,v);
printf("%d\n",ans);
}
} return ;
}

kuangbin专题 专题九 连通图 POJ 3694 Network的更多相关文章

  1. kuangbin专题 专题九 连通图 POJ 1236 Network of Schools

    题目链接:https://vjudge.net/problem/POJ-1236 题目:有向图,有若干个连通图,点之间有单向边边就可以单向传递信息,问: (1)至少需要发送几份信息才能使得每个点都传递 ...

  2. Poj 3694 Network (连通图缩点+LCA+并查集)

    题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...

  3. POJ 3694——Network——————【连通图,LCA求桥】

    Network Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  4. kuangbin专题 专题九 连通图 POJ 3177 Redundant Paths

    题目链接:https://vjudge.net/article/371?tdsourcetag=s_pcqq_aiomsg 题目:给定一个连通图,题目说,任意两个点至少有一条路线可以相互到达, 为保证 ...

  5. poj 3694 Network 边双连通+LCA

    题目链接:http://poj.org/problem?id=3694 题意:n个点,m条边,给你一个连通图,然后有Q次操作,每次加入一条边(A,B),加入边后,问当前还有多少桥,输出桥的个数. 解题 ...

  6. [双连通分量] POJ 3694 Network

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9434   Accepted: 3511 Descripti ...

  7. POJ 3694 Network (tarjan + LCA)

    题目链接:http://poj.org/problem?id=3694 题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥. 首先用t ...

  8. poj 3694 Network(双连通分量)

    题目:http://poj.org/problem?id=3694 #include <iostream> #include <cstring> #include <cs ...

  9. poj 3694 Network(割边+lca)

    题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...

随机推荐

  1. Cookie内不能直接存入中文,cookie转码以及解码

    如果在cookie中存入中文,极易出现问题. js在存入cookie时,利用escape() 函数可对字符串进行编码, 用unescape()进行解码 顺序是先把cookie用escape()函数编码 ...

  2. P1091 剧院广场

    题目描述 柏林首都的剧院广场呈长方形,面积为 \(n \times m\) 平方米.在这座城市的周年纪念日之际,人们决定用方形花岗岩石板铺设广场.每块石板的大小都是 \(a \times a\) . ...

  3. element-ui tree 根据不同叶子节点设置是否显示复选框

    公司业务要求不同根节点配置显示与否复选框,官方文档没有这样的配置,所以想到了修改element-ui源码. 1.这里将“node_modules\element-ui\packages”下的tree文 ...

  4. C# 性能分析 反射 VS 配置文件 VS 预编译

    本文分析在 C# 中使用反射和配置文件和预编译做注入的性能,本文的数据是为预编译框架,开发高性能应用 - 课程 - 微软技术暨生态大会 2018 - walterlv提供 本文通过代码生成工具,使用C ...

  5. JavaSE基础---多线程

    进程:正在进行的程序.其实就是一个应用程序运行时的内存分配空间. 线程:进程中一个程序执行控制单元,一条执行路径.进程负责的事应用程序的空间的标识,线程负责的事应用程序的执行顺序. 进程和线程的关系: ...

  6. Recall(召回率);Precision(准确率);F1-Meature(综合评价指标);true positives;false positives;false negatives..

    转自:http://blog.csdn.net/t710smgtwoshima/article/details/8215037   Recall(召回率);Precision(准确率);F1-Meat ...

  7. 编写jQuery插件的方法和注意点

    编写jQuery插件的方法和注意点 插件的种类 jQuery的插件主要分为3种类型. 1. 封装对象方法的插件 这种插件是将对象方法封装起来,用于对通过选择器获取的jQuery对象进行操作,是最常见的 ...

  8. git push报错大文件,删除后重新commit依然报错

    git push报错: github不能上传大文件,按道理删掉重新提交就行了 可是删掉后,git add -A,再git commit,再git push,依然报错 后来我想明白了 github上传时 ...

  9. Android 最新架构

    1.Android系统架构 最新的Android系统分为五层六区(域): Linux内核层(Linux Kernel):Android系统基于Linux2.6内核,这一层为Android设备各种硬件提 ...

  10. 通过Servlet生成验证码图片(转)

    一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedImage类,如下: