并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)
题意:
有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通。有两种操作:
1. 删去a到b的一条边
2. 询问a到b的稳定性
思路:
首先删边考虑离线,倒着做,相对于加边。先用并查集建一棵树,最精简的图,初始化树上的每条边权值为1,那么在a和b点加一条边的话,会使a到b的链上所有边因为这条新边而稳定性贡献无效,这样我们可以树链剖分,用线段树维护链上的边的稳定性贡献值。
#include <bits/stdc++.h>
using namespace std; const int N = 3e4 + 5;
const int M = 1e5 + 5;
int n, m, q; struct Edge {
int v, nex;
}edge[M<<2];
int head[N];
int etot; void init_edge() {
memset (head, -1, sizeof (head));
etot = 0;
} void add_edge(int u, int v) {
edge[etot] = (Edge) {v, head[u]};
head[u] = etot++;
} #define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1 int sum[N<<2], lazy[N<<2]; void push_up(int o) {
sum[o] = sum[o<<1] + sum[o<<1|1];
} void push_down(int l, int r, int o) {
if (lazy[o] != -1) {
lazy[o<<1] = lazy[o];
lazy[o<<1|1] = lazy[o];
int mid = l + r >> 1;
sum[o<<1] = lazy[o] * (mid - l + 1);
sum[o<<1|1] = lazy[o] * (r - mid + 1);
lazy[o] = -1;
}
} void build(int l, int r, int o) {
lazy[o] = -1;
if (l == r) {
sum[o] = 1;
return ;
}
int mid = l + r >> 1;
build (lson);
build (rson);
push_up (o);
} int query(int ql, int qr, int l, int r, int o) {
if (ql <= l && r <= qr) {
return sum[o];
}
push_down (l, r, o);
int mid = l + r >> 1, ret = 0;
if (ql <= mid) ret += query (ql, qr, lson);
if (qr > mid) ret += query (ql, qr, rson);
return ret;
} void updata(int ql, int qr, int c, int l, int r, int o) {
if (ql <= l && r <= qr) {
sum[o] = (r - l + 1) * c;
lazy[o] = c;
return ;
}
push_down (l, r, o);
int mid = l + r >> 1;
if (ql <= mid) updata (ql, qr, c, lson);
if (qr > mid) updata (ql, qr, c, rson);
push_up (o);
} int sz[N], fa[N], dfn[N], belong[N];
int tim; void DFS2(int u, int chain) {
dfn[u] = ++tim;
belong[u] = chain;
int k = 0;
for (int i=head[u]; ~i; i=edge[i].nex) {
Edge &e = edge[i];
if (e.v == fa[u]) continue;
if (sz[e.v] > sz[k]) k = e.v;
}
if (k) DFS2 (k, chain);
for (int i=head[u]; ~i; i=edge[i].nex) {
Edge &e = edge[i];
if (e.v == fa[u] || e.v == k) continue;
DFS2 (e.v, e.v);
}
} void DFS(int u, int pa) {
sz[u] = 1;
fa[u] = pa;
for (int i=head[u]; ~i; i=edge[i].nex) {
Edge &e = edge[i];
if (e.v == pa) continue;
DFS (e.v, u);
sz[u] += sz[e.v];
}
} int query_ans(int u, int v) {
int ret = 0;
int p = belong[u], q = belong[v];
while (p != q) {
if (dfn[p] < dfn[q]) {
swap (p, q);
swap (u, v);
}
ret += query (dfn[p], dfn[u], 1, n, 1);
u = fa[p];
p = belong[u];
}
if (dfn[u] < dfn[v]) swap (u, v);
if (u != v) {
ret += query (dfn[v]+1, dfn[u], 1, n, 1);
}
return ret;
} void modify(int u, int v) {
int p = belong[u], q = belong[v];
while (p != q) {
if (dfn[p] < dfn[q]) {
swap (p, q);
swap (u, v);
}
updata (dfn[p], dfn[u], 0, 1, n, 1);
u = fa[p];
p = belong[u];
}
if (dfn[u] < dfn[v]) swap (u, v);
if (u != v) {
updata (dfn[v]+1, dfn[u], 0, 1, n, 1);
}
} void prepare() {
sz[0] = 0;
DFS (1, 0);
tim = 0;
DFS2 (1, 1);
build (1, n, 1);
} int rt[N]; int Find(int x) {
return rt[x] == x ? x : rt[x] = Find (rt[x]);
} multiset<pair<int, int> > mset1, mset2;
int op[M], x[M], y[M];
int ans[M]; int main() {
int T, cas = 0;
scanf ("%d", &T);
while (T--) {
init_edge ();
scanf ("%d%d%d", &n, &m, &q);
for (int i=1; i<=n; ++i) {
rt[i] = i;
}
mset1.clear ();
for (int i=1; i<=m; ++i) {
int u, v;
scanf ("%d%d", &u, &v);
if (u > v) swap (u, v);
mset1.insert ({u, v});
}
for (int i=1; i<=q; ++i) {
scanf ("%d%d%d", &op[i], &x[i], &y[i]);
if (x[i] > y[i]) swap (x[i], y[i]);
if (op[i] == 1) mset1.erase (mset1.find ({x[i], y[i]}));
}
mset2.clear ();
for (auto &it: mset1) {
int p = Find (it.first), q = Find (it.second);
if (p == q) continue;
mset2.insert (it);
add_edge (it.first, it.second);
add_edge (it.second, it.first);
rt[p] = q;
} prepare (); for (auto &it: mset1) {
if (mset2.find (it) == mset2.end ()) {
modify (it.first, it.second);
}
}
for (int i=q; i>=1; --i) {
if (op[i] == 1) {
modify (x[i], y[i]);
} else {
ans[i] = query_ans (x[i], y[i]);
}
} printf ("Case #%d:\n", ++cas);
for (int i=1; i<=q; ++i) {
if (op[i] == 2) {
printf ("%d\n", ans[i]);
}
}
}
return 0;
}
并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)的更多相关文章
- 2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)
链接:https://ac.nowcoder.com/acm/contest/553/I 思路:离线整棵树,用并查集维护下联通的情况,因为值只有60个,用2的x(1<=x<=60)次方表示 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]
题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个 ...
- 【Codeforces827D/CF827D】Best Edge Weight(最小生成树性质+倍增/树链剖分+线段树)
题目 Codeforces827D 分析 倍增神题--(感谢T*C神犇给我讲qwq) 这道题需要考虑最小生成树的性质.首先随便求出一棵最小生成树,把树边和非树边分开处理. 首先,对于非树边\((u,v ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- 【bzoj1606】[Usaco2008 Dec]Hay For Sale 购买干草
题目描述 约翰遭受了重大的损失:蟑螂吃掉了他所有的干草,留下一群饥饿的牛.他乘着容量为C(1≤C≤50000)个单位的马车,去顿因家买一些干草. 顿因有H(1≤H≤5000)包干草,每一包都有它的体 ...
- Qt &QSS
Today task:解决了qt中的一些控件无法使用qss的问题(如QProgressDialog 调节chunk的颜色,QMessageBox按钮的颜色问题)1,对于QMessageBox,可以单独 ...
- pycharm快捷键及一些常用设置
pycharm快捷键及一些常用设置,有需要的朋友可以参考下. Alt+Enter 自动添加包 Ctrl+t SVN更新 Ctrl+k SVN提交 Ctrl + / 注释(取消注释)选择的行 Ctrl+ ...
- linux 下C++查询mysql数据库
上一节我们看了怎么使用mysql提供的API来连接mysql数据库,现在来看看怎么执行一条简单的查询语句,并且把查询的结果显示出来. 准备工作:首先新建了一个数据库inote,在这个数据库下面新建了一 ...
- javascript 性能惰性加载2016.12.13
利用函数的惰性载入提高 javascript 代码性能 原文:利用函数的惰性载入提高javascript代码性能 作者:阿安 在 javascript 代码中,因为各浏览器之间的行为的差异,我们经常会 ...
- 在WPF中使用WinForm控件方法
1. 首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2. 在要使用WinForm控 ...
- nodejs 编写(添加时间戳)命令行工具 timestamp
Nodejs除了编写服务器端程序还可以编写命令行工具,如gulp.js就是Nodejs编写的. 接下来我们来实现一个添加时间戳的命令: $ timestamp action https://www.n ...
- 使用Visual Leak Detector for Visual C++ 捕捉内存泄露
什么是内存泄漏? 内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段 ...
- dubbox rest服务
1.xml配置: web.xml 定义监听的contextpath,见rest协议定义 <servlet> <servlet-name>dispatcher</servl ...
- 无线连接Android设备
有时设备处于低电,此时又需要进行设备与PC的数据传输,但是通过USB连接充电速度太慢.这时就可以通过无线进行传输数据,然后通过AC充电.一举两得. 前提: 1.在Android设备的开发者模式-打开U ...