UOJ 150|NOIP 2015 Day 2|运输计划|LCA
来源:互联网 发布:java有证书吗 编辑:程序博客网 时间:2024/06/04 18:06
Description
给出N点树和M条树上简单路径,求将一条边的边权改为0后使M条路径中最长的最短,求最小化的最长路径的长度。
Method
题目描述来看容易联系到二分答案,当我们二分长度时,显然不需要考虑比二分的答案要短的路径,对于长的路径,我们只能修改一条边的长度,因此这条边必须在较长路径中都出现,即这些路径的路径交上的边。
考虑序列上的区间交的求法,即在两端点打标记,那么将某个区间归属于其左端点,求前缀和后若某端点的前缀和=区间数量,那么其表示的区间是区间交的一部分。当然区间交是连续的。
在树上也可以这么做,在路径两端点和LCA处打标记,这里我们将某条边归属于深度较大的端点上。那么就从叶节点到根的方向求一次前缀和(倒BFS序),前缀和值=路径数量的点所表示的边就是路径交的一部分。
这个算法显然是
当初考场上打了个
Summary
以上思路可以注意到:
1. 在二分答案最优化时,关于判定是否满足答案,已经已经满足条件的无须理会,直接关注不满足条件,需要进行调整的数据之间的共同点,比如本题显然不满足条件的路径的共同点或关键点就是路径交上的边。
2. 树上问题优先考虑列上,再套用LCA和拓扑排序(边上问题,本题就是边上的)或是树链剖分(点上问题)转化到树上。
Code
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,j,k) for(i=j;i<=k;++i)int read() { int s = 0, f = 1; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1; for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0'; return s * f;}const int N = 300005, M = N * 2, K = 18;int h[N], p[M], v[M], w[M], q[M], cnt = 0;int fa[N][K + 1], dep[N], dis[N];int mx[M], my[M], mlen[M], mlca[M], m, n;int topo[N], tnum = 0, stk[N], flag[N];void add(int a, int b, int c) { p[++cnt] = h[a]; v[cnt] = b; w[cnt] = c; h[a] = cnt;}int dfs(int x) { int i, top = 0; stk[++top] = x; while (top) { topo[++tnum] = x = stk[top--]; FOR(i,1,K) fa[x][i] = fa[fa[x][i - 1]][i - 1]; for (i = h[x]; i; i = p[i]) if (v[i] != fa[x][0]) { fa[v[i]][0] = x; q[v[i]] = w[i]; dep[v[i]] = dep[x] + 1; dis[v[i]] = dis[x] + w[i]; stk[++top] = v[i]; } }}int lca(int x, int y) { if (dep[x] < dep[y]) swap(x, y); int t = dep[x] - dep[y], i; FOR(i,0,K) if (t & (1 << i)) x = fa[x][i]; for (i = K; ~i; --i) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return x == y ? x : fa[x][0];}bool judge(int mid) { int i, delta = 0, num = 0; FOR(i,1,n) flag[i] = 0; FOR(i,1,m) if (mlen[i] > mid) { flag[mx[i]]++; flag[my[i]]++; flag[mlca[i]] -= 2; delta = max(delta, mlen[i] - mid); ++num; } if (!num) return true; for (i = tnum; i; --i) flag[fa[topo[i]][0]] += flag[topo[i]]; FOR(i,1,n) if (flag[i] == num && q[i] >= delta) return true; return false;}int main() { int i, a, b, c, ans = 0; n = read(); m = read(); FOR(i,2,n) { a = read(); b = read(); c = read(); add(a, b, c); add(b, a, c); } dfs(1); a = b = 0; FOR(i,1,m) { mx[i] = read(); my[i] = read(); mlca[i] = lca(mx[i], my[i]); mlen[i] = dis[mx[i]] + dis[my[i]] - 2 * dis[mlca[i]]; b = max(b, mlen[i]); } while (a <= b) { c = a + b >> 1; if (judge(c)) b = c - 1, ans = c; else a = c + 1; } printf("%d", ans); return 0;}
[NOIP 2015 Day2]运输计划
公元 2044 年,人类进入了宇宙纪元。
L 国有
小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从
为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了
如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
输入格式
第一行包括两个正整数
接下来
接下来
输出格式
输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
样例一
input
6 31 2 31 6 43 1 74 3 63 5 53 62 54 5
output
11
explanation
将第
将第
将第
将第
将第
故将第
限制与约定
时间限制:
空间限制:
- UOJ 150|NOIP 2015 Day 2|运输计划|LCA
- NOIP 2015 && UOJ#150 运输计划
- NOIp 2015 运输计划 LCA
- 【bzoj 4326】【codevs 4632】【UOJ #150】[NOIP 2015]运输计划(dfs+lca+二分答案+差分)
- BZOJ_P4326[NOIP]2015 运输计划(LCA+Tarjan+二分)
- UOJ 150 [NOIP2015]运输计划
- NOIP[2015] 运输计划
- NOIP 2015 运输计划
- 【noip 2015】运输计划
- NOIP 2015 运输计划
- NOIP 2015 Day 2 transport 运输计划 (树链剖分 序列差分 二分答案)
- [FT][???]NOIP 2015 运输计划
- 4632 NOIP[2015] 运输计划
- NOIP 2015 Day2 T3 运输计划(二分+dfs序+树上差分+倍增LCA)
- 【uoj#150】【NOIP2015】运输计划 树上前缀和+lca+二分+拓扑排序+特别的卡常数技巧
- noip运输计划(倍增lca,树上差分)
- NOIP 2015 [D2 T3]运输计划
- 【BZOJ 4326】【NOIP 2015 d2t3】运输计划
- linux--时间编程(5)
- C++STL之string
- 纯新手向--Linux搭建SVN服务器
- Word Pattern
- hdu1429 胜利大逃亡(续)--BFS
- UOJ 150|NOIP 2015 Day 2|运输计划|LCA
- Xcode 7 缺少 *.dylib库的解决方法
- 前后端完全分离
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'systemLogAsp
- iPhone屏幕尺寸、分辨率及适配
- 按照原计划,继续全力以赴
- JAVA 解析复杂的json字符串
- NSProcessInfo获取进程信息,UIDevice获取设信息
- POJ 3278Catch That Cow(BFS)