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并查集+连通图求桥)
就是求出原先图中的桥的数量,在每一次询问时加入一条新边,求加入当前边后图中剩余的桥的数量 求出原先图中的桥的数量,然后减去新加入边的两端点之间的桥的数量,就是剩余桥的数量.. 用并查集把属于同一集合的 ...
随机推荐
- 关于highchts X时间轴比设置时间相差好几个小时的解决
经过一番查询和研究发现,在曲线图里,x轴的UNIX时间戳是要乘以1000的(通过在线的UNIX转换,结果与原来没有乘以1000的时间戳相差甚远),不然显示的时间会有很大的误差,真是百思不得其解. 另外 ...
- netstat Recv-Q和Send-Q详解
http://blog.csdn.net/sjin_1314/article/details/9853163 通过netstat -anp可以查看机器的当前连接状态: Active Interne ...
- ios xmpp demo
为了方便程序调用,我们把XMPP的一些主要方法写在AppDelegate中 在AppDelegate.m下这几个方法为: [java] view plaincopy -(void)setupStrea ...
- 用vue 简单写的日历
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Python爬虫环境常用库安装
1:urllib urllib.request这两个库是python自带的库,不需要重新安装,在python中输入如下代码: import urllibimport urllib.requestres ...
- docker:安装mysql
文章来源:https://www.cnblogs.com/hello-tl/p/9234429.html 1.添加镜像 docker pull mysql 2.在/data下新建文件夹mysql,进入 ...
- Python之路-基础数据类型之列表 元组
列表的定义 列表是Python基础数据类型之一,它是以[ ]括起来, 每个元素用' , '隔开而且可以存放各种数据类型: lst = [1,2,'你好','num'] 列表的索引和切片 与字符串类似, ...
- wordpress配置SMTP服务发送邮件(qq邮箱)
wordpress有一个注册功能,填了用户名和邮箱后,会收到一封邮件,邮件里有一个链接,点击该链接可以获得密码和修改密码.但是,最开始,你会发现,等半天都没有收到邮件,再等到猴年马月也不会收到. 但是 ...
- appIcon
原文地址:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconM ...
- 我的第一个ajax脚本
代码如下 //创建XMLHttpRequest对象 var xmlHttp=null; function creatXMLHttp(){ try{ xmlHttp = new XMLHttpReque ...