P4172 [WC2006]水管局长
Posted hnylmstea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4172 [WC2006]水管局长相关的知识,希望对你有一定的参考价值。
[LCT]P4172水管局长
(Solution)
如果没有删除,那么就是维护一个最小生成树,然后倍增求两点之间的最大边权(货车运输).
因为有删边操作,想到LCT
,但这是删除,最大值不满足减法,所以不好搞。
但注意到只有删除没有添加,所以我们可以倒过来处理,一条一条边link
维护最小生成树以及两点间最大值,这样最大值就变成可加的了。
倒着处理,如果要加一条边u->v
,那么先查询u->v
的最大边权(假如这条边为x->y
),如果要加的边权比这还大,那么就忽略(贪心),否则就删掉x->y
,再link(u, v)
. (ps:因为要知道x->y
对应的边是什么,所以可以用 map<pair<int, int> >
)
一个小技巧:因为LCT维护的是点上的信息,所以我们边化点.如果要连x
到y
,且这条边编号z
,那么就执行link(x, z + n), link(z + n, y)
(Source)
#include <map>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>
using namespace std;
#define fir first
#define sec second
#define pb push_back
#define mp make_pair
#define LL long long
#define INF (0x3f3f3f3f)
#define mem(a, b) memset(a, b, sizeof (a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(x) cout << #x << " = " << x << endl
#define tralve(i, x) for (register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
#define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
namespace io {
static char buf[1<<21], *pos = buf, *end = buf;
inline char getc()
{ return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
inline int rint() {
register int x = 0, f = 1;register char c;
while (!isdigit(c = getc())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
return x * f;
}
inline LL rLL() {
register LL x = 0, f = 1; register char c;
while (!isdigit(c = getc())) if (c == '-') f = -1;
while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
return x * f;
}
inline void rstr(char *str) {
while (isspace(*str = getc()));
while (!isspace(*++str = getc()))
if (*str == EOF) break;
*str = '