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颗也相 ...
随机推荐
- node.js内存泄露问题记录
先说一下.事情的来龙去脉. 公司开发一款游戏棋牌游戏,服务端的开发是IO密集型,开发的时候,考虑过使用python,java,node.js. 终于选择了node.js(node.js宣传的杀手功能. ...
- Vue 之 npm 及 安装的包
1 npm相关 1.1 npm 是 基于Node.js 的,所以要先安装Node.js 在浏览器地址栏输入https://nodejs.org/en/, 进入Node.js官网后,点击下载左边的稳定 ...
- SpringMVC中返回JSON时乱码的解决方案
springMVC中返回JSON会出现乱码,解决如下: produces = "text/html;charset=UTF-8" @ResponseBody @RequestMap ...
- debian apt-get工作的原理
1 apt-get update apt-get update并没有将远程仓库的包都下载到本地,而是通过访问远程仓库创建或者更新了远程仓库的本地索引,索引文件放在/var/lib/apt/lists目 ...
- Rowkey is the Crux Rowkey Design
Apache HBase ™ Reference Guide http://hbase.apache.org/book.html#rowkey.design The Effect of ColumnF ...
- C语言文件读写Demo
CIODemo.c #include <stdio.h> #include <time.h> #define INPUT_BUFFER_SIZE 100 * 1024 int ...
- ⭐驱动之module_init/module_exit与系统启动关系
在前面helloworld的编写里面,我们使用了两个宏分别是module_init和module_exit,这里分析下为什么使用这两个宏. 在写模块的时候有两个特殊的函数,分别是init_module ...
- 常用: JS 获取浏览器窗口大小
// 获取窗口宽度 if (windows.innerWidth) winWidth = windows.innerWidth; else if ((document.body) && ...
- ODC(Orthogonal Defect Classification)简介——正交缺陷分类法
Defect分析是软件开发和测试中一个重要的环节,ODC介绍了一种不同于大家常用的非常有效的defect分类及分析方法.这篇文章简单的向大家介绍了什么是ODC,以及如何在项目和产品开发中使用ODC来改 ...
- 一步一步学Silverlight 2系列(8):使用样式封装控件观感
述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...