Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)
题目链接:
题目描述:
给出一个还有环和重边的图G,对图G有两种操作:
1 u v, 删除u与v之间的一天边 (保证这个边一定存在)
2 u v, 查询u到v的路径上有几条桥。
解题思路:
这个题目有很多次操作,包含查询和删边两类,首先想到的是连通分量加缩点。如果按照顺序来,删边时候求桥就是问题了。所以可以离线处理,然后一边记录答案一边加边缩点。
对于一个图,把连通分量缩成一个点后,这个图就成为了一棵树, 然后深度差就等于桥的数目。查询的时候对于(u, v)桥的数目等于(设定deep[x]为x的深度,LCA(x, y)为(x, y)的父节点) deep[u] + deep[v] - 2 * deep[LCA(u, v)];
现在问题就成了怎么才能更快的缩点和维护点的深度。
缩点问题:在树上加上一条边就会形成一个环,然后这个环(强连通分量)上点就会被缩成一个点,然后用并查集来维护强联通分量,每次只需要合并父节点(每个点只能被缩一次,复杂度被平摊还是很可观的)。
维护节点深度:每次儿子节点合并到父亲节点的时候,儿子节点的子孙节点的深度都要减一。在这里我们可以用dfs序 + 树状数组来维护节点的深度。利用树状数组的区间更改点查询优化维护深度的操作。
还有最后一个问题就是计算(u, v)节点之间桥数目的时候,需要用到LCA,可以利用树上倍增LCA来优化时间复杂度。
这个题目还是很值得本扎扎练手的,考察了很多东西,真是把压箱底的东西都翻出来晒了晒,仰慕当场ac的聚聚们。
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = ;
const int N = ;
const int M = ; struct node
{
int to, del;
node(int x):to(x),del() {}
bool operator < (const node & a) const
{
if (to != a.to) return to < a.to;
return del > a.del;
}
};
vector <node> vec[maxn]; struct Query
{
int op, u, v;
void read ()
{
scanf ("%d %d %d", &op, &u, &v);
if (op == )
{
lower_bound (vec[u].begin(), vec[u].end(), node(v)) -> del = true;
lower_bound (vec[v].begin(), vec[v].end(), node(u)) -> del = true;
}
}
} query[N]; int n, m, q; void init ()
{
for (int i=; i<=n; i++)
vec[i].clear();
} struct bit_tree
{
int tree[maxn]; void init()
{
memset (tree, , sizeof(tree));
} int lowbit (int x)
{
return x & (-x);
} void change (int x, int num)
{
while (x <= n)
{
tree[x] += num;
x += lowbit (x);
}
} void update (int x, int y, int num)
{
change (x, num);
change (y+, -num);
} int query (int x)
{
int res = ;
while (x)
{
res += tree[x];
x -= lowbit (x);
}
return res;
} }Bit_tree; int begin_id[maxn], end_id[maxn], deep[maxn], ntime;
int fa[maxn][M];
void dfs (int u, int father, int dep)
{
if (father > )
vec[u].erase (lower_bound(vec[u].begin(), vec[u].end(), node(father))); fa[u][] = father;
begin_id[u] = ++ntime;
deep[u] = dep; for (int i=; i<vec[u].size(); i++)
{
node p = vec[u][i];
if (p.del || begin_id[p.to]) continue;
vec[u][i].del = true;
dfs (p.to, u, dep+);
} end_id[u] = ntime;
Bit_tree.update (begin_id[u], end_id[u], );
} struct Lca
{
void init ()
{
for (int i=; i<M; i++)
for (int j=; j<=n; j++)
fa[j][i] = fa[fa[j][i-]][i-];
} int lca (int u, int v)
{
if (deep[u] < deep[v]) swap (u, v);
int num = deep[u] - deep[v];
for (int i=; i<M; i++)
if ((<<i) & num) u = fa[u][i];
if (u == v) return u;
for (int i=M-; i>=; i--)
if (fa[u][i] != fa[v][i])
{
u = fa[u][i];
v = fa[v][i];
}
return fa[u][];
} }LCA; int father[maxn];
struct UNion
{
void init()
{
for (int i=; i<=n; i++)
father[i] = i;
} int find (int x)
{
if (x != father[x]) father[x] = find (father[x]);
return father[x];
} void merge_fa (int x, int y)
{
x = find (x);
while (x != y)
{
int t = find(fa[x][]);
father[x] = t;
Bit_tree.update(begin_id[x], end_id[x], -);
x = t;
}
} void merge (int x, int y)
{
int l = find (LCA.lca (x, y));
merge_fa (x, l);
merge_fa (y, l);
} }Union; int ans[N], res;
void solve ()
{
Bit_tree.init ();
ntime = res = ;
memset (begin_id, , sizeof(begin_id));
dfs (, , );
LCA.init ();
Union.init(); for (int i=; i<=n; i++)
{
for (int j=; j<vec[i].size(); j++)
{
node p = vec[i][j];
if (p.del) continue;
Union.merge (p.to, i);
}
} for (int i=q; i>; i--)
{
Query p = query[i];
int u = begin_id[p.u];
int v = begin_id[p.v];
int x = begin_id[LCA.lca(p.u, p.v)];
if (p.op == )
Union.merge(p.u, p.v);
else
ans[++ res] = Bit_tree.query(u) + Bit_tree.query(v) - *Bit_tree.query(x);
} while(res)
printf ("%d\n", ans[res --]);
} int main ()
{
int t, u, v;
scanf ("%d", &t); for (int i=; i<=t; i++)
{
scanf("%d %d %d", &n, &m, &q);
init (); for (int j=; j<m; j++)
{
scanf ("%d %d", &u, &v);
vec[u].push_back (node(v));
vec[v].push_back (node(u));
} for (int j=; j<=n; j++)
sort (vec[j].begin(), vec[j].end()); for (int j=; j<=q; j++)
query[j].read(); printf ("Case #%d:\n", i);
solve (); }
return ;
}
Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)的更多相关文章
- hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)
hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...
- HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...
- BZOJ-3211花神游历各国 并查集+树状数组
一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...
- BZOJ3211 花神游历各国 并查集 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3211 题意概括 有n个数形成一个序列. m次操作. 有两种,分别是: 1. 区间开根(取整) 2. ...
- 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组
题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...
- HDU 4750 Count The Pairs ★(图+并查集+树状数组)
题意 给定一个无向图(N<=10000, E<=500000),定义f[s,t]表示从s到t经过的每条路径中最长的边的最小值.Q个询问,每个询问一个t,问有多少对(s, t)使得f[s, ...
- la4730(并查集+树状数组)
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=30& ...
- 【BZOJ3211】花神游历各国 并查集+树状数组
[BZOJ3211]花神游历各国 Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 41 100 5 551 1 22 1 ...
- 【BZOJ4382】[POI2015]Podział naszyjnika 堆+并查集+树状数组
[BZOJ4382][POI2015]Podział naszyjnika Description 长度为n的一串项链,每颗珠子是k种颜色之一. 第i颗与第i-1,i+1颗珠子相邻,第n颗与第1颗也相 ...
随机推荐
- git svn 报错
删除 openjdk 时 remove 了一大堆软件. 可能由于这个原因导致使用 git svn 命令时出现类似下面的错误. sam@sam-CW65S:pics$ git svn rebase Ca ...
- <十二>读<<大话设计模式>>之状态模式
对于状态模式,<<大话设计模式>>是以人从上班到下班到加班的状态来展开讲述的.状态模式事实上就是某一个对象在某个过程或者时间的一个状态记录,可是这个状态的顺序不能发生变化.在程 ...
- [攻防实战]CTF大赛准备(手动注入sql)
一.IIS write漏洞利用 先用工具扫描,再上传小马,使用菜刀连接即可. 思考点: 如何获知是一台IIS站点? 本例中上传的一句话木马是什么意思? <%eval request(" ...
- mac的终端窗口的工作组的使用
1.打开终端,打开多个tab,分别进入目录, 2.点击窗口,将窗口存储为组,弹窗如下图 可以勾选恢复所有命令,存储 3.下次使用时,点击窗口,打开工作组即可
- HashMap随机取值和迭代器取值的对比
一共四中方法,前两种是迭代器取值,后两种是随机取值,循环了5000万次,时间分别为:迭代器读取的速度大约是随机读取的速度的1.5倍,数据量越大,差距越明显. 另外,插入是读取的100倍左右的时间(这个 ...
- 20170218 OO-ALV标准工具栏按钮
原文地址:OO ALV 工具栏对于的功能码 图标与对应的 功能码 明细 &DETAIL 检查 &CHECK 刷新 &REFRESH 剪切 &LOCAL&CU ...
- JS中使用组合构造函数模式和原型模式
创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式.构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性. 结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的 ...
- Spring Boot 整合Filter
两种方法 方法一: 正常创建好Filter类,配置完成 package clc.user.filter; import javax.servlet.Filter; import javax.servl ...
- jquery 获取radio被选中的值
<html> <head> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"& ...
- Healthy Holsteins
链接 分析:因为数据范围比较小,我们可以通过二进制枚举子集,然后找出所需饲料种数最小的并记录下来,同时记录一下路径,也就是字典序最小的 /* PROB:holstein ID:wanghan LANG ...