bzoj 4326 运输计划 (树链剖分 + 树上差分 + 二分)
2017-10-26 10:37
441 查看
不想贴题面系列……
这道题就是先二分一个答案,然后check,如果路线的总长度比二分的答案大,就把它们拎出来进行树上差分(求它们所有路线都经过的边),然后把这条边的权值减掉(贪心),反复check即可。
这道题就是先二分一个答案,然后check,如果路线的总长度比二分的答案大,就把它们拎出来进行树上差分(求它们所有路线都经过的边),然后把这条边的权值减掉(贪心),反复check即可。
#include <bits/stdc++.h> using namespace std; const int N = 300010; int n, m; struct E { int v, w, next; } e[N << 1]; int num = 0, head[N << 1]; void add(int u, int v, int w) { e[++ num].v = v; e[num].w = w; e[num].next = head[u]; head[u] = num; } struct Node { int s, t, len, lca; } car ; int fa , son , siz , dep , dis , top ; void dfs1(int u, int f, int d) { siz[u] = 1; fa[u] = f; dep[u] = d; for(int i = head[u]; i; i = e[i].next) { int v = e[i].v; if(v == f) continue; dis[v] = dis[u] + e[i].w; dfs1(v, u, d + 1); siz[u] += siz[v]; if(siz[son[u]] < siz[v]) son[u] = v; } } void dfs2(int u, int tp) { top[u] = tp; if(! son[u]) return ; dfs2(son[u], tp); for(int i = head[u]; i; i = e[i].next) { int v = e[i].v; if(v == fa[u] || v == son[u]) continue; dfs2(v, v); } } int getlca(int u, int v) { int fu = top[u], fv = top[v]; while(fu != fv) { if(dep[fu] < dep[fv]) swap(fu, fv), b5b3 swap(u, v); u = fa[fu], fu = top[u]; } if(dep[u] > dep[v]) swap(u, v); return u; } int tot, delta, mmax, flag ; void dfs(int u, int W) { for(int i = head[u]; i; i = e[i].next) { int v = e[i].v; if(v == fa[u]) continue ; dfs(v, e[i].w); flag[u] += flag[v]; } if(flag[u] == tot) delta = max(W, delta); } bool check(int mid) { tot = delta = mmax = 0; memset(flag, 0, sizeof(flag)); for(register int i = 1; i <= m; ++ i) if(car[i].len > mid) { ++ tot; mmax = max(mmax, car[i].len - mid); flag[car[i].s] ++, flag[car[i].t] ++, flag[car[i].lca] -= 2; } dfs(1, 0); if(mmax - delta > 0) return 0; return 1; } int main() { scanf("%d %d", &n, &m); for(register int i = 1; i < n; ++ i) { int u, v, w; scanf("%d %d %d", &u, &v, &w); add(u, v, w); add(v, u, w); } dfs1(1, 0, 1); dfs2(1, 1); int l = 0, r = 0; for(register int i = 1; i <= m; i ++) { scanf("%d %d", &car[i].s, &car[i].t); car[i].lca = getlca(car[i].s, car[i].t); car[i].len = dis[car[i].s] + dis[car[i].t] - 2 * dis[car[i].lca]; r = max(r, car[i].len); } while(l < r) { int mid = (l + r) >> 1; if(check(mid)) r = mid; else l = mid + 1; } printf("%d\n", l); return 0; }
相关文章推荐
- bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- 【BZOJ】4326 NOIP2015 运输计划 二分+LCA+树上差分
- bzoj4326【2015提高】运输计划(二分答案+lca+树上差分前缀和)
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
- BZOJ 4326: NOIP2015 运输计划 二分答案 树上差分
- [BZOJ4326][NOIP2015]运输计划(二分答案+树上差分)
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- [BZOJ4326][NOIP2015][倍增][二分][差分序列]运输计划
- [二分+差分]BZOJ 4326——NOIP2015 运输计划
- bzoj4326 & UOJ150【NOIP2015】运输计划 ( 树上差分 + lca )
- [二分答案 树链剖分] BZOJ 4326 NOIP2015 运输计划
- bzoj 4326: NOIP2015 运输计划 (二分答案+树链剖分+树状数组)
- BZOJ 4326: NOIP2015 运输计划【LCA】【二分】【差分】
- 【BZOJ4326】【二分答案】【树上差分】NOIP2015 D2T3 运输计划 题解
- LCA+二分+树上差分——Luogu2680 [NOIP2015]运输计划
- 【NOIP2015】运输计划(树上差分,二分答案)
- BZOJ 4326 NOIP 2015 DAY2 T3 浅谈二分及树上差分数组DFS动态统计
- P2680 运输计划(二分+树上差分)