长春市网站建设_网站建设公司_原型设计_seo优化
2025/12/18 20:28:15 网站建设 项目流程

P2680 [NOIP 2015 提高组] 运输计划

大意

给你一棵树,一堆航线,航线之间有边权,让你输出最晚的航线最快啥时候到。

思路

首先就是最大值最小,我们可以考虑进行二分,二分答案 \(k\),也就是说当前的所有航线的路程需要小于等于 \(k\),我们知道,每次改完,最多能让一个航线的值减去 \(1\),我们只需要判断这些大于等于 \(k\) 的航线交集最多的那条边即可。

于是我们的思路就出来了,二分 \(k\),找交集最大的边,判断是否合法。

然后找交集的过程我们可以采用树上差分。

代码

#include<iostream>
#include<algorithm>
using namespace std;const int MAXN = 600005;
const int LOG = 19;int n, m;struct node{int to, nxt, len;
}e[MAXN];
int tot = 0, h[MAXN], dep[MAXN];
int d[MAXN], f[MAXN][LOG];
int sum[MAXN];
struct N{int u, v, val, lca;
}p[MAXN];
void add(int x, int y, int len){e[++ tot] = {y, h[x], len};h[x] = tot;
}void dfs(int u, int fa){dep[u] = dep[fa] + 1;f[u][0] = fa;for(int i = h[u];i;i = e[i].nxt){int v = e[i].to;if(v == fa) continue;sum[v] = sum[u] + e[i].len;dfs(v, u);}
}void I_nt(){for(int k = 1;k < LOG;k ++){for(int i = 1;i <= n;i ++){f[i][k] = f[f[i][k - 1]][k - 1];}}
}int LCA(int u, int v){if(dep[u] < dep[v]) swap(u, v);for(int k = LOG - 1;k >= 0;k --){if(dep[f[u][k]] >= dep[v]){u = f[u][k];}}if(u == v) return u;for(int k = LOG - 1;k >= 0;k --){if(f[u][k] != f[v][k]){u = f[u][k];v = f[v][k];}}return f[u][0];
}int tmp, ans;void dfs2(int u, int fa){for(int i = h[u];i;i = e[i].nxt){int v = e[i].to;if(v == fa) continue;dfs2(v, u);d[u] += d[v];}if(d[u] == tmp){ans = max(ans, sum[u] - sum[f[u][0]]);}
}bool check(int mid){for(int i = 1;i <= n;i ++) d[i] = 0;tmp = 0;for(int i = 1;i <= m;i ++){if(p[i].val > mid){tmp ++;d[p[i].u] ++;d[p[i].v] ++;d[p[i].lca] -= 2;}else break;}ans = -1e9;dfs2(1, 0);if(p[1].val - ans > mid){return false;}return true;
}int main(){ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for(int i = 1;i < n;i ++){int u, v, w; cin >> u >> v >> w;add(u, v, w), add(v, u, w);}dfs(1, 0);I_nt();int l = 0, r = 0;for(int i = 1;i <= m;i ++){cin >> p[i].u >> p[i].v;p[i].lca = LCA(p[i].u, p[i].v);p[i].val = (sum[p[i].u] + sum[p[i].v] - 2 * sum[p[i].lca]);r = max(r, p[i].val);}sort(p + 1, p + m + 1, [](N a, N b){return a.val > b.val;});while(l <= r){int mid = (l & r) + ((l ^ r) >> 1);if(check(mid)){//mid is okr = mid - 1;}else{l = mid + 1;}}cout << l << '\n';return 0;
}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询