noip2015运输计划
有一棵带边权有根树,有m个运输计划,你可以把一条边变成0,所有计划一起开始
求完成所有计划的最短时间
sol:
先二分,我们发现,用时mid以下的计划是没用的(要所有计划都完成)
mid以上的计划,如果不相交,直接就是false
如果相交,找到他们最大的一条交边,把那条边变成0,然后看最大计划 - 最大交边边权是否大于mid
不大于mid就是true
求交边可以用树上差分
树上差分统计的时候可以用dfs序,可以...省栈空间
#include<bits/stdc++.h> #define LL long long using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int maxn = 300010; int n,m; struct edg{int to,val;}; vector<edg> G[maxn]; int lg[maxn],fa[maxn],dep[maxn],delt[maxn],dis[maxn],bl[maxn],size[maxn]; int ui[maxn],vi[maxn],dfn[maxn],DFN; int LCA[maxn],len[maxn]; inline void dfs1(int x) { size[x] = 1; for(auto data : G[x]) { int to = data.to,va = data.val; if(to == fa[x])continue; fa[to] = x; dep[to] = dep[x] + 1;dis[to] = dis[x] + va; dfs1(to);size[x] += size[to]; } } inline void dfs2(int x,int col) { int k = 0; bl[x] = col;dfn[++DFN] = x; for(auto data : G[x]) { int to = data.to,va = data.val; if(size[to] > size[k] && dep[to] > dep[x])k = to; } if(!k)return; dfs2(k,col); for(auto data : G[x]) { int to = data.to,va = data.val; if(to != k && dep[to] > dep[x])dfs2(to,to); } } inline int lca(int x,int y) { while(bl[x] != bl[y]) { if(dep[bl[x]] < dep[bl[y]])swap(x,y); x = fa[bl[x]]; } return dep[x] < dep[y] ? x : y; } inline int caldis(int x,int y){return dis[x] + dis[y] - 2 * dis[lca(x,y)];} int nowu[maxn],nowv[maxn]; inline void getdelt(int x) { for(auto data : G[x]) { int to = data.to; if(to == fa[x])continue; getdelt(to);delt[x] += delt[to]; } } inline int chk(int x) { memset(delt,0,sizeof(delt)); int curlen = 0,mx = 0,cnt = 0,maxw = 0; for(int i=1;i<=m;i++) if(caldis(ui[i],vi[i]) > x) { delt[ui[i]]++; delt[vi[i]]++; delt[lca(ui[i],vi[i])] -= 2; mx = max(mx,caldis(ui[i],vi[i])); cnt++; } for(int i=n;i>=2;i--) { delt[fa[dfn[i]]] += delt[dfn[i]]; if(delt[dfn[i]] == cnt)maxw = max(maxw,dis[dfn[i]] - dis[fa[dfn[i]]]); } // cout<<mx - maxw<<":"<<x<<endl; return mx - maxw <= x; } int main() { int mx = 0; n = read(),m = read(); for(int i=2;i<=n;i++) { int u = read(),v = read(),w = read(); //mx = max(mx,w); G[u].push_back((edg){v,w});G[v].push_back((edg){u,w}); }dfs1(1);dfs2(1,1); //return 0; for(int i=1;i<=m;i++) { ui[i] = read(),vi[i] = read(); LCA[i] = lca(ui[i],vi[i]); len[i] = dis[ui[i]] + dis[vi[i]] - 2 * dis[LCA[i]]; mx = max(mx,len[i]); } //return 0; int l = 0,r = mx,ans; //cout<<l<<" "<<r<<endl; while(l <= r) { int mid = (l + r) >> 1; if(chk(mid))r = mid - 1,ans = mid; else l = mid + 1; } cout<<ans<<endl; }