POJ 3694 (tarjan缩点+LCA+并查集)
好久没写过这么长的代码了,题解东哥讲了那么多,并查集优化还是很厉害的,赶快做做前几天碰到的相似的题。
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std; const int N = 1e5 + , M = 2e5 + ;
int head[N], ver[M * ], Next[M * ];
int dfn[N], low[N], n, m, tot, num;
bool bridge[M * ]; void add(int x, int y)
{
ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
void tarjan(int x, int in_edge)
{
dfn[x] = low[x] = ++num;
for(int i = head[x]; i; i = Next[i])
{
int y = ver[i];
if(!dfn[y])
{
tarjan(y, i); ///节点 和 入边
low[x] = min(low[x], low[y]); if(low[y] > dfn[x])
{
bridge[i] = bridge[i ^ ] = true;
}
}
else if(i != (in_edge ^ )) ///搜索树上的边
{
low[x] = min(low[x], dfn[y]);
}
}
}
int c[N], dcc;
void dfs(int x)
{
c[x] = dcc;
for(int i = head[x]; i; i = Next[i])
{
int y = ver[i];
if(c[y] || bridge[i]) continue;
dfs(y);
}
}
const int maxn = N;
///加边
int cnt, h[maxn];
struct edge
{
int to, pre, v;
} e[maxn << ];
void add(int from, int to, int v)
{
cnt++;
e[cnt].pre = h[from]; ///5-->3-->1-->0
e[cnt].to = to;
e[cnt].v = v;
h[from] = cnt;
}
///LCA
int dist[maxn];
int dep[maxn];
int anc[maxn][]; ///2分的父亲节点
void dfs(int u, int fa)
{
for(int i = h[u]; i; i = e[i].pre)
{
int v = e[i].to;
if(v == fa) continue;
dist[v] = dist[u] + e[i].v;
dep[v] = dep[u] + ;
anc[v][] = u;
dfs(v, u);
}
}
void LCA_init(int n)
{
for(int j = ; ( << j) < n; j++)
for(int i = ; i <= n; i++) if(anc[i][j-])
anc[i][j] = anc[anc[i][j-]][j-];
}
int LCA(int u, int v)
{
int log;
if(dep[u] < dep[v]) swap(u, v);
for(log = ; ( << log) < dep[u]; log++);
for(int i = log; i >= ; i--)
if(dep[u] - ( << i) >= dep[v]) u = anc[u][i];
if(u == v) return u;
for(int i = log; i >= ; i--)
if(anc[u][i] && anc[u][i] != anc[v][i])
u = anc[u][i], v = anc[v][i];
return anc[u][];
}
int fa[N];
int Find(int x)
{
if(x == fa[x]) return x;
return fa[x] = Find(fa[x]);
}
int main()
{
int kase = ;
while(scanf("%d %d", &n, &m) != EOF)
{
if(n == && m == ) break;
tot = , dcc = , cnt = ;
for(int i = ; i <= n; i++) head[i] = , dfn[i] = , low[i] = , c[i] = , h[i] = ;
for(int i = ; i <= m * + ; i++) ver[i] = , Next[i] = , bridge[i] = false;
for(int i = ; i <= m; i++)
{
int x, y; scanf("%d %d", &x, &y);
add(x, y), add(y, x);
}
///求桥
for(int i = ; i <= n; i++)
{
if(!dfn[i]) tarjan(i, );
}
///求边双连通分量
for(int i = ; i <= n; i++)
{
if(!c[i])
{
++dcc;
dfs(i);
}
}
///缩点
for(int i = ; i <= tot; i++)
{
int x = ver[i ^ ], y = ver[i];
if(c[x] == c[y]) continue;
add(c[x], c[y], );
}
dfs(, );
LCA_init(dcc);
///并查集初始化
for(int i = ; i <= dcc; i++) fa[i] = i;
int Q; scanf("%d", &Q);
int ans = dcc - ;
printf("Case %d:\n", ++kase);
while(Q--)
{
int x, y; scanf("%d %d", &x, &y);
x = c[x], y = c[y];
int p = LCA(x, y);
x = Find(x);
while(dep[x] > dep[p])
{
fa[x] = anc[x][];
ans--;
x = Find(x);
}
y = Find(y);
while(dep[y] > dep[p])
{
fa[y] = anc[y][];
ans--;
y = Find(y);
}
printf("%d\n", ans);
}
}
return ;
}
POJ 3694 (tarjan缩点+LCA+并查集)的更多相关文章
- Poj 3694 Network (连通图缩点+LCA+并查集)
题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...
- POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)
[题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...
- POJ3694 Network 边双缩点+LCA+并查集
辣鸡错误:把dfs和ldfs搞混...QAQ 题意:给定一个无向图,然后查询q次,求每次查询就在图上增加一条边,求剩余割边的个数. 先把边双缩点,然后预处理出LCA的倍增数组: 然后加边时,从u往上跳 ...
- POJ3694 Network —— 边双联通分量 + 缩点 + LCA + 并查集
题目链接:https://vjudge.net/problem/POJ-3694 A network administrator manages a large network. The networ ...
- Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...
- Tarjan 模板,高级并查集
第一个模板有误!!!! 请见谅!!! 要怪就怪HDU吧,竟然让我过了 第二个模板是正确的.请翻到下面看更新 HDU 1269 评论区居然有人说用并查集过了,其实回想一下 求无向图的连通分量,就是并查集 ...
- 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
[题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...
- POJ 2762 tarjan缩点+并查集+度数
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15494 ...
- Network POJ - 3694(lca并查集+连通图求桥)
就是求出原先图中的桥的数量,在每一次询问时加入一条新边,求加入当前边后图中剩余的桥的数量 求出原先图中的桥的数量,然后减去新加入边的两端点之间的桥的数量,就是剩余桥的数量.. 用并查集把属于同一集合的 ...
随机推荐
- tomcat假死现象(转)
1.1 编写目的 为了方便大家以后发现进程假死的时候能够正常的分析并且第一时间保留现场快照. 1.2编写背景 最近服务器发现tomcat的应用会偶尔出现无法访问的情况.经过一段时间的观察最近又发现有台 ...
- BXS入门赛部分writeup
pwn1 盲打(笑) 前言:没有听鱼哥的话,事先没有装好环境,于是开始没做出来,然后全程在装pwntools,经过一番努力,失败了0.0 最终在网上搜了一段python socket连接脚本,终于可 ...
- jpeg和jpg的区别是什么
JPG是JPEG的简写,jpg是后缀名,jpeg既可作为后缀名,又能代表文件格式:JPG——JPEG文件格式. 我们在系统自带的画图程序里保存文件,在保存类型:JPEG(*.JPG,*.JPEG,*. ...
- iOS 面试集锦2
4.写一个setter方法用于完成@property (nonatomic,retain)NSString *name,写一个setter方法用于完成@property(nonatomic,copy) ...
- UNIX环境C语言进程通信
一.信号管理 1.函数signal signal函数是UNIX系统信号机制最简单的接口 #include <signal.h> typedef void (*sighandler_t)(i ...
- 编译openwrt_MT7688_hiwooya
参考链接: 无涯论坛地址: http://www.hi-wooya.com/forum.php openwrt官网地址:https://openwrt.org/zh-cn/doc/howto/buil ...
- SpringMVC里静态网页不能加载到.js .css文件的问题
在写SpringMVC项目时候,写的js css文件打不开,网上查了一下,解决办法: 在web.xml里面: <servlet> <servlet-name>dispatche ...
- 我的Python分析成长之路2
2018-12-29 一.python数据类型: 1.数字 int(整形) float(浮点型) complex(复数型) 2.布尔值(bool) 真或假 True or False 3.字符 ...
- java之 单根继承与集合
1.单根继承 概念: 单根继承,意味着所有类的继承,都继承自单一的基类的继承模式 优点: (1)所有对象都具有一个共用接口,归根到底都是相同的基本类型. (1)所有对象都具有一个共用接口,归根到底都是 ...
- Knockout v3.4.0 中文版教程-5-计算监控-使用计算监控
3. 计算监控 1.使用计算监控 如果你有一个监控的属性firstName和另一个lastName,但你想显示全名怎么办? 这就是引入计算监控的原因-这是依赖于一个或多个其他的observables函 ...