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颗也相 ...
随机推荐
- (org.openqa.selenium.WebDriverException: Unable to launch the app: Error: Trying to start logcat capture but it's already started! )错误解决办法
新增: capabilities.setCapability("autoLaunch",false); 将setup中的: driver = new AndroidDriver(n ...
- Quartz深入浅出(二)
Hello Quartz / 本文通过一个简单的样例让大家高速了解Quartz,上手.并了解Quartz内的一些关键对象 如 Scheduler.Job.Trigger.JobExecutionCon ...
- scala进阶笔记:函数组合器(combinator)
collection基础参见之前的博文scala快速学习(二). 本文主要是组合器(combinator),因为在实际中发现很有用.主要参考:http://www.importnew.com/3673 ...
- 读写ini配置文件 .
ini文件的第一行不能是有效内容(不能为section),否则读出键值为空. INI文件是一个无固定标准格式的设置档.它以简单的文字与简单的结构组成,常常使用在视窗操作系统,或是其他操作系统上,许多程 ...
- 设计模式学习笔记——Mediator中介者模式
将众多对象之间的网状关系转为全部通过一个中间对象间接发生关系,此中间对象为中介者. 看图最直观: 作用不言而喻,就是降低对象之间的耦合度,乃至降低了整个系统的复杂度. 有点象代理模式,更象外观模式:
- Eclipse设置java环境
通用JRE环境设置: Window->Preferences->Java->Installed JREs 设置jre路径,如C:\Program Files\Java\jre1.8. ...
- openfire学习(一)
需要开发一款软件,其中的即时通讯功能使用xmpp协议来做,服务端用openfire. openfire的下载和配置就不多说,可能大多数人第一次用会遇到登陆不了的问题,我也遇到了,事实上登陆错误是因为用 ...
- 搭建java运行环境
安装IDE 集成开发环境(IDE,Integrated Development Environment ) 1.安装jdk,jre(jdk自带jre),记住他们的安装位置. 2.配置环境变量.(JAV ...
- poj 1469 COURSES 解题报告
题目链接:http://poj.org/problem?id=1469 题目意思:有 N 个人,P个课程,每一个课程有一些学生参加(0个.1个或多个参加).问 能否使得 P 个课程 恰好与 P 个学生 ...
- jsp项目上传到服务器
我们通过Myeclipse完成一个Java web项目时只能通过本地访问来查看,但是我们想把它上传到服务器上使用外网访问应该怎么做呢,首先肯定是要有一台服务器 个人调试项目试手的话我建议去买阿里云的云 ...