1. 程式人生 > >[隊內測試Day10.22T4][洛谷P2680]運輸計劃

[隊內測試Day10.22T4][洛谷P2680]運輸計劃

題目←

吐槽下考場上的魔改題面……
看出來是運輸計劃後,記得以前聽說過是二分,於是開始摸魚……
不會樹鏈剖分,考場上卡掉一個點
儘管實現步驟很麻煩,但思路清晰的話,具體打起來還是比較容易的一道題
能摸出來大概是人品比較好……

#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const LL MAXN = 300000 + 50;
struct edge{
    LL f,t,v;
}l[MAXN << 1
]; struct zt{ LL f,t; LL v; LL lca; }e[MAXN]; LL head[MAXN],next[MAXN << 1],tot; void init(LL n){ for(LL i = 1;i <= n;i ++){ head[i] = -1; } } void build(LL f,LL t,LL v){ l[++ tot] = (edge){f,t,v}; next[tot] = head[f]; head[f] = tot; } LL n,m,a,b,c; LL deep[MAXN],fa[MAXN][26
]; LL ru[MAXN]; LL rank[MAXN]; void dfs(LL p,LL f){ for(LL i = 1;i <= 25;i ++){ fa[f][i] = fa[fa[f][i - 1]][i - 1]; } for(LL i = head[f];i != -1;i = next[i]){ LL t = l[i].t; if(t == p)continue; ru[t] ++; deep[t] = deep[f] + 1; fa[t][0] = f; rank[t] = rank[f] + l[i].v; dfs(f,t); } } LL LCA(LL a,LL b){ if
(deep[a] < deep[b])swap(a,b); LL t = deep[a] - deep[b]; for(LL i = 0;i <= 25;i ++){ if(t & (1 << i)){ a = fa[a][i]; } } if(a == b)return a; for(LL i = 25;i >= 0;i --){ if(fa[a][i] != fa[b][i]){ a = fa[a][i]; b = fa[b][i]; } } return fa[a][0]; } LL topo[MAXN]; LL L = 1,R = 1; void toposort(){ topo[R ++] = 1; while(L != R){ LL u = topo[L]; for(LL i = head[u];i != -1;i = next[i]){ LL t = l[i].t; ru[t] --; if(!ru[t])topo[R ++] = t; } L ++; } } LL mid; LL cf[MAXN]; bool check(LL x){ LL cnt = 0; LL maxx = 0; for(LL i = 0;i <= n;i ++){ cf[i] = 0; } for(LL i = 1;i <= m;i ++){ if(e[i].v > x){ cf[e[i].f] ++; cf[e[i].t] ++; cf[e[i].lca] --; cf[fa[e[i].lca][0]] --; cnt ++; maxx = max(maxx,e[i].v); } } for(LL j = n;j >= 1;j --){ LL u = topo[j]; for(LL i = head[u];i != -1;i = next[i]){ LL t = l[i].t; if(deep[t] < deep[u])continue; cf[u] += cf[t]; } } for(LL u = 1;u <= n;u ++){ if(cf[u] < cnt)continue; for(LL i = head[u];i != -1;i = next[i]){ if(deep[l[i].t] < deep[u])continue; if(cf[l[i].t] >= cnt){ if(maxx - l[i].v <= x)return true; } } } return false; } void solve(){ R ++; L --; while(R - L > 1){ mid = L + R >> 1; if(check(mid))R = mid; else L = mid; } } int main(){ freopen("Random.in","r",stdin); freopen("Random.out","w",stdout); scanf("%lld%lld",&n,&m); init(n); for(LL i = 1;i <= n - 1;i ++){ scanf("%lld%lld%lld",&a,&b,&c); build(a,b,c); build(b,a,c); } dfs(1,1); toposort(); L = R = 0; for(LL i = 1;i <= m;i ++){ scanf("%lld%lld",&e[i].f,&e[i].t); LL lca = LCA(e[i].f,e[i].t); e[i].v = rank[e[i].f] + rank[e[i].t] - 2*rank[lca]; e[i].lca = lca; R = max(R,e[i].v); } solve(); printf("%lld",R); fclose(stdin); fclose(stdout); return 0; }