Brief Description

您有一个无向带权图,您需要支持两种操作。

  1. 询问两个点之间的最大权最小路径。
  2. 删除一条边。

Algorithm Design

我们首先提出一个猜想:最优路径一定在原图的一个最小生成森林上,证明如下:

假设最优路径有\(\phi\)条边不再最小生成森林上,我们考察其中的一条边,根据定义,生成森林中一定有一条路径链接这条边的顶点且权值和小于这条边,那么我们如果使用这条路径代替这条边,\(\phi\)会减小而最大权不会增加,所以根据反证法我们就可以知道这个结论的正确性。

有了这个引理之后我们可以把原题转化为维护一个最小生成森林,这显然可以使用lct维护。

考虑细节。因为lct不是太支持删一条边,所以我们离线地倒过来做。

另外我们需要记录每条边是否被删。我开始使用了map,然而不知道为什么一直RE。后来改用二分查找就好了。所以——

抵制STL从我做起!(逃#

Code

#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
const int maxv = 1500005;
int read() {
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
struct data {
int from, to, dat, br, id;
data(int x = 0, int y = 0, int z = 0, int i = 0, int j = 0)
: from(x), to(y), dat(z), br(i), id(j) {}
bool operator<(const data b) const {
return this->from < b.from || ((this->from == b.from) && (this->to < b.to));
}
} a[1000005];
struct req {
int opt, x, y, id, ans;
req(int x = 0, int y = 0, int z = 0, int k = 0, int fuck = 0) {
this->opt = x;
this->x = y;
this->y = z;
this->id = k;
this->ans = fuck;
}
} q[100005];
bool cmp(data a, data b) { return a.dat < b.dat; }
bool cmp2(data a, data b) { return a.id < b.id; }
int n, m, qaq, f[maxv], max[maxv], val[maxv], tot, maxnum[maxv];
int fa[maxv], ch[maxv][2];
bool rev[maxv];
int bisearch(int u, int v) {
int l = 1, r = m;
while (l <= r) {
int mid = (l + r) >> 1;
if (a[mid].from < u || (a[mid].from == u && a[mid].to < v))
l = mid + 1;
else if (a[mid].from == u && a[mid].to == v)
return mid;
else
r = mid - 1;
}
return -1;
}
bool isroot(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
void pushdown(int k) {
if (rev[k]) {
rev[k] ^= 1;
rev[ch[k][0]] ^= 1;
rev[ch[k][1]] ^= 1;
std::swap(ch[k][0], ch[k][1]);
}
}
void update(int x) {
maxnum[x] = x;
int l = maxnum[ch[x][0]], r = maxnum[ch[x][1]];
if (val[l] > val[maxnum[x]])
maxnum[x] = l;
if (val[r] > val[maxnum[x]])
maxnum[x] = r;
max[x] = val[maxnum[x]];
}
void zig(int x) {
int y = fa[x], z = fa[y], l = (ch[y][1] == x), r = l ^ 1;
if (!isroot(y))
ch[z][ch[z][1] == y] = x;
fa[ch[y][l] = ch[x][r]] = y;
fa[ch[x][r] = y] = x;
fa[x] = z;
update(y);
update(x);
}
void splay(int x) {
int s[maxv], top = 0;
s[++top] = x;
for (int i = x; !isroot(i); i = fa[i])
s[++top] = fa[i];
while (top)
pushdown(s[top--]);
for (int y; !isroot(x); zig(x)) {
if (!isroot(y = fa[x])) {
zig((ch[fa[y]][0] == y) == (ch[y][0] == x) ? y : x);
}
}
update(x);
}
void access(int x) {
for (int t = 0; x; t = x, x = fa[x]) {
splay(x);
ch[x][1] = t;
update(x);
}
}
void makeroot(int x) {
access(x);
splay(x);
rev[x] ^= 1;
}
void split(int x, int y) {
makeroot(y);
access(x);
splay(x);
}
void link(int x, int y) {
makeroot(x);
fa[x] = y;
}
void cut(int x, int y) {
makeroot(x);
access(y);
splay(y);
ch[y][0] = fa[x] = 0;
}
void init() {
memset(val, 0, sizeof(val));
n = read();
m = read();
qaq = read();
for (int i = 1; i <= n; i++)
f[i] = i;
for (int i = 1; i <= m; i++) {
int x = read(), y = read(), z = read();
if (x > y)
std::swap(x, y);
a[i] = data(x, y, z);
}
std::sort(a + 1, a + 1 + m, cmp);
for (int i = 1; i <= m; i++) {
a[i].id = i;
val[n + i] = a[i].dat;
maxnum[n + i] = n + i;
}
std::sort(a + 1, a + 1 + m);
for (int i = 1; i <= qaq; i++) {
int x = read(), y = read(), z = read();
q[i] = req(x, y, z);
if (x == 2) {
if (q[i].x > q[i].y)
std::swap(q[i].x, q[i].y);
int t = bisearch(q[i].x, q[i].y);
a[t].br = 1;
q[i].id = a[t].id;
}
}
}
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void kruskal() {
std::sort(a + 1, a + m + 1, cmp2);
tot = 0;
for (int i = 1; i <= m; i++) {
if (!a[i].br) {
int u = a[i].from, v = a[i].to, x = find(u), y = find(v);
if (x != y) {
f[x] = y;
link(u, i + n);
link(v, i + n);
tot++;
if (tot == n - 1)
break;
}
}
}
}
void solve() {
for (int i = qaq; i >= 1; i--) {
int op = q[i].opt, x = q[i].x, y = q[i].y;
if (op == 1) {
split(x, y);
q[i].ans = val[maxnum[x]];
}
if (op == 2) {
int k = q[i].id;
split(x, y);
int t = maxnum[x];
if (a[k].dat < val[t]) {
cut(a[t - n].from, t);
cut(a[t - n].to, t);
link(x, k + n);
link(y, k + n);
}
}
}
for (int i = 1; i <= qaq; i++) {
if (q[i].opt == 1)
printf("%d\n", q[i].ans);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
init();
kruskal();
solve();
return 0;
}

[bzoj2594][Wc2006]水管局长数据加强版——lct+离线的更多相关文章

  1. [bzoj2594][Wc2006]水管局长数据加强版 (lct)

    论蒟蒻的自我修养T_T.. 和noi2014魔法森林基本一样...然而数据范围大得sxbk...UPD:这题如果用lct判联通的话可能会被卡到O(mlogm)..所以最好还是用并查集吧 一开始数组开太 ...

  2. BZOJ2594 [Wc2006]水管局长数据加强版 LCT kruskal

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2594 题意概括 N个点的图,M条带权边.(N<=100000,M<=1000000) ...

  3. bzoj2594 [Wc2006]水管局长数据加强版——LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2594 时间倒序一下,就是 魔法森林 那道题: 有个不解的地方,是 access 里面关于 p ...

  4. BZOJ2594: [Wc2006]水管局长数据加强版

    题解: 裸LCT+离线+二分+MST... 代码:(几乎摘抄自hzwer) #include<cstdio> #include<cstdlib> #include<cma ...

  5. BZOJ 2594: [Wc2006]水管局长数据加强版 [LCT kruskal]

    2594: [Wc2006]水管局长数据加强版 Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 2917  Solved: 918[Submit][St ...

  6. BZOJ 2594: [Wc2006]水管局长数据加强版( LCT )

    离线然后就是维护加边的动态MST, Link cut tree秒掉..不过我写+调了好久...时间复杂度O(NlogN + MlogM) ------------------------------- ...

  7. BZOJ2594 [Wc2006]水管局长数据加强版 【LCT维护最小生成树】

    题目 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的 ...

  8. [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)

    传送门 WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题! ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹 理一下思路吧 题目大意:给定一个无向图,多次删除图中的 ...

  9. BZOJ 2594: [Wc2006]水管局长数据加强版 (LCT维护最小生成树)

    离线做,把删边转化为加边,那么如果加边的两个点不连通,直接连就行了.如果联通就找他们之间的瓶颈边,判断一下当前边是否更优,如果更优就cut掉瓶颈边,加上当前边. 那怎么维护瓶颈边呢?把边也看做点,向两 ...

随机推荐

  1. Git 上传本地仓库到码云

    一.将本地的项目上传到码云 1.码云上创建一个项目 testgit (名字随你) 2.本地创建一个文件夹D:/testgit,然后使用git bash 3.cd 到本地文件夹中D:/testgit 4 ...

  2. 在阿里云上遇见更好的Oracle(四)

    2016.5.13,北京,第七届数据库技术大会. 从最初的itpub社区,到后来被it168收购,DBA社区的线下聚会发展成2010年第一届数据库技术大会(DTCC).第一届大会汇聚了社区内活跃的各位 ...

  3. 感知机学习算法(PLA)

    Perception Learning Algorithm, PLA 1.感知机 感知机是一种线性分类模型,属于判别模型. 感知机模型给出了由输入空间到输出空间的映射: f(X) = sign(WTX ...

  4. Regularization method for machine learning

    Regularization method(正则化方法) Outline Overview of Regularization L0 regularization L1 regularization ...

  5. 使用idea工具开发webservice

    在idea开发工具中使用axis2插件创建集成webservice的web项目: 一.创建java项目                  二.添加webservices支持 在红线框2处选择要使用的w ...

  6. 第5讲——cin处理字符输入

    本来这一讲应该是while.for.if之类的,但是,我们可是学过C的男人,再浪费时间搞这个??? 还不如学点C++中的新知识. cin对象支持3种不同模式的单字符输入,其用户接口各不相同. 下面我们 ...

  7. 提高python执行效率的方法

    python上手很容易,但是在使用过程中,怎么才能使效率变高呢? 下面说一下提高python执行效率的方法,这里只是说一点,python在引入模块过程中提高效率的方法. 例如: 1.我们要使用os模块 ...

  8. javascript实现自动切换焦点功能学习

    当用户在表单中填写完当前字段后,能否自动将焦点跳转到下一个字段以方便用户输入? 为了增强易用性,加快数据输入的速度,可以在前一个文本框中的字符达到一定的设置的字符长度后(比如电话号码,身份证号等),用 ...

  9. C语言数组作业总结

    数组作业总结 评分注意事项. 注意用Markdown语法排版,尤其注意伪代码用代码符号渲染.用符号 ``` 生成代码块. 变量名不规范,没注释,没缩进,括号不对齐,倒扣5分. PTA上写的所有代码务必 ...

  10. WCF扩展记录服务调用时间

    WCF 提供了许多扩展点供开发人员自定义运行时行为. WCF 在 Channel Layer 之上还提供了一个高级运行时,主要是针对应用程序开发人员.在 WCF 文档中,它常被称为服务模型层(Serv ...