[NOIp2015][二分][LCA] 運輸計劃
阿新 • • 發佈:2020-08-19
題面
// 二分一個路徑長,並要求所有長度大於該 // 長度的路徑經過同一條邊,且該邊的長度 // 比每條路徑的長度與二分路徑長度差值大, // 即為所求答案。 // 差分陣列用於確定是否每條路徑都經過該邊 # include <iostream> # include <cstdio> # include <cstring> # define MAXN 300005 struct Edge{ int v, w, next; }e[MAXN<<1]; struct Query{ int x, y; int lca, dis; }q[MAXN]; struct node{ int fa, hSon, dep, top, siz, dis; }nd[MAXN]; int hd[MAXN], cntE, d[MAXN], co[MAXN]; // d 是差分陣列 int n, m;int seg[MAXN], cntS; int L, R; template<typename T> void rd(T & x); void AddE(int u, int v, int w); void PreDFS(int now, int fa); void SegDFS(int now, int top); int GetLCA(int x, int y); bool chk(int val); int main(){ rd<int>(n), rd<int>(m); for(int i = 1, u, v, w; i <= n-1; i++){ rd<int>(u), rd<int>(v), rd<int>(w); AddE(u, v, w); AddE(v, u, w); L = std::max(L, w); } PreDFS(1, 0); SegDFS(1, 1); for(int i = 1; i <= m; i++){ rd<int>(q[i].x), rd<int>(q[i].y); q[i].lca = GetLCA(q[i].x, q[i].y); q[i].dis = nd[q[i].x].dis + nd[q[i].y].dis - (nd[q[i].lca].dis*2); R = std::max(R, q[i].dis); } int l = R-L, r = R+1; while(l < r){ int mid = (l + r) >> 1; if(chk(mid)){ r = mid; } else{ l = mid+1; } } printf("%d", l); return 0; } bool chk(int val){ memset(d, 0, sizeof(d)); int cntSu = 0; for(int i = 1; i <= m; i++){ if(q[i].dis > val){ d[q[i].x]++, d[q[i].y]++, d[q[i].lca] -= 2; cntSu++; } } for(int i = n; i >= 1; i--){ d[nd[seg[i]].fa] += d[seg[i]]; if(co[seg[i]] >= R - val && d[seg[i]] == cntSu){ return 1; } } return 0; } int GetLCA(int x, int y){ while(nd[x].top != nd[y].top){ if(nd[nd[x].top].dep < nd[nd[y].top].dep){ std::swap(x, y); } x = nd[nd[x].top].fa; } return nd[x].dep < nd[y].dep ? x : y; } void SegDFS(int now, int top){ nd[now].top = top; if(!nd[now].hSon){ return; } SegDFS(nd[now].hSon, top); for(int i = hd[now]; i; i = e[i].next){ if(e[i].v == nd[now].fa || e[i].v == nd[now].hSon){ continue; } SegDFS(e[i].v, e[i].v); } } void PreDFS(int now, int fa){ nd[now].fa = fa, nd[now].dep = nd[fa].dep + 1; nd[now].siz = 1; seg[++cntS] = now; for(int i = hd[now]; i; i = e[i].next){ if(e[i].v == fa){ continue; } co[e[i].v] = e[i].w; nd[e[i].v].dis = nd[now].dis + e[i].w; // 注意這句話的位置 PreDFS(e[i].v, now); nd[now].siz += nd[e[i].v].siz; if(nd[e[i].v].siz > nd[nd[now].hSon].siz){ nd[now].hSon = e[i].v; } } } void AddE(int u, int v, int w){ e[++cntE].v = v, e[cntE].next = hd[u], hd[u] = cntE; e[cntE].w = w; } template<typename T> void rd(T & x){ x = 0; T fl = 1; int ch = getchar(); for( ;!isdigit(ch); ch = getchar()){ if(ch == '-'){ fl = -1; } } for( ; isdigit(ch); ch = getchar()){ x = x * 10 + ch - '0'; } x *= fl; }