洛谷 P2680
题目链接:P2680 运输计划
题目大意
题目要求的是我们找一条边,可以让这条边的权值变成0,然后给了你几对点,让你求在改变边的权值之后的最大值,然后输出最小的最大值
solution
最小值最大? 二分答案.
那我们可以用LCA+树上差分来做(就这样不想写了)
code:
/**
* Author: Alieme
* Data: 2020.8.26
* Problem: Luogu P2680
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 1000010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
struct Node {
int u;
int v;
int lca;
int diss;
}lu[MAXN];
struct Edge {
int nxt;
int to;
int val;
Edge() {}
Edge(int Nxt, int To, int Val) {nxt = Nxt, to = To, val = Val;}
}e[MAXN];
int tot, n, m, cnt;
int head[MAXN], dep[MAXN], dis[MAXN], temp[MAXN], num[MAXN];
int fa[MAXN][30];
inline void add(int from, int to, int val) {
e[++tot] = Edge(head[from], to, val);
head[from] = tot;
}
void dfs(int x, int fath) {
num[++cnt] = x;
dep[x] = dep[fath] + 1;
fa[x][0] = fath;
for (rr int i = 1; i < 25; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (rr int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == fath) continue;
dis[to] = dis[x] + e[i].val;
dfs(to, x);
}
}
inline int LCA(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
int t = dep[x] - dep[y];
for (rr int i = 0; i < 25; i++)
if ((1 << i) & t)
x = fa[x][i];
if (x == y) return x;
for (rr int i = 24; i >= 0; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
inline bool check(int x) {
int cnt = 0, ans = 0;
memset(temp, 0, sizeof temp);
for (rr int i = 1; i <= m; i++)
if (lu[i].diss > x) {
temp[lu[i].u]++;
temp[lu[i].v]++;
temp[lu[i].lca] -= 2;
ans = max(ans, lu[i].diss - x);
cnt++;
}
if (cnt == 0) return true;
for (rr int i = n; i >= 1; i--) temp[fa[num[i]][0]] += temp[num[i]];
for (rr int i = 2; i <= n; i++) if (temp[i] == cnt && dis[i] - dis[fa[i][0]] >= ans) return true;
return false;
}
signed main() {
n = read();
m = read();
for (rr int i = 1; i < n; i++) {
int u = read();
int v = read();
int w = read();
add(u, v, w);
add(v, u, w);
}
dis[1] = 0;
dfs(1, 0);
for (rr int i = 1; i <= m; i++) {
lu[i].u = read();
lu[i].v = read();
lu[i].lca = LCA(lu[i].u, lu[i].v);
lu[i].diss = dis[lu[i].u] + dis[lu[i].v] - 2 * dis[lu[i].lca];
}
int l = 0, r = inf;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
print(l);
}
时间会刺破青春表面的彩饰,会在美人的额上掘深沟浅槽;会吃掉稀世之珍!天生丽质,什么都逃不过他那横扫的镰刀。
博主写的那么好,就不打赏一下么(打赏在右边)