题目链接:https://loj.ac/p/6405
给出n个点的一棵树,每个点有xi个军队,需要yi个军队,你可以移动军队,求使得满足所有点要求的情况下,军队移动路径和的最小值。
1≤n≤250000,军队总数和不超过106。
一看就是费用流,但是数据范围很大所有是模拟费用流。
那么考虑贪心,因为我们要贪心所以我们很难强制满流,那么我们就定义一个流量会额外带上一个−∞的权值,然后最后答案加上∞×c就好了。
那么考虑一个流量从x流到y,费用是depx+depy−deplca×2−∞,如果一个是需要军队的,那么定义valx=depx−∞,否则valx=depx。
那么就可以视费用为valx+valy−deplca×2,那么这些答案我们就可以在lca处维护了,设它们的lca为z。
考虑用可并堆储存子树内的valx和valy,然后每次取出最小的直到valx+valy−depz×2≥0为止,但是我们还需要一个退流的操作,也就是可撤回的过程。这个过程我们的权值是相反的,定义新的val′x=2×depz−valy,同理val′y=2×depz−valx就好了。
时间复杂度:O(nlogn)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=3e6+10,inf=1e12;
struct Heap{
ll cnt,w[N],t[N][2],dis[N];
ll Merge(ll x,ll y){
if(!x||!y)return x|y;
if(w[x]>w[y])swap(x,y);
t[x][1]=Merge(t[x][1],y);
if(dis[t[x][0]]<dis[t[x][1]])
swap(t[x][0],t[x][1]);
dis[x]=dis[t[x][1]]+1;
return x;
}
ll Delete(ll x)
{return Merge(t[x][0],t[x][1]);}
void Ins(ll &x,ll val){
++cnt;w[cnt]=val;
x=Merge(x,cnt);
}
}T1,T2;
struct node{
ll to,next,w;
}a[N<<1];
ll n,tot,ans,ls[N],rt1[N],rt2[N],dep[N],c[N];
void addl(ll x,ll y,ll w){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;a[tot].w=w;
return;
}
void dfs(ll x,ll fa){
if(c[x]<0){
for(int i=0;i<-c[x];i++)
T1.Ins(rt1[x],dep[x]-inf);
}
if(c[x]>0){
for(int i=0;i<c[x];i++)
T2.Ins(rt2[x],dep[x]);
}
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa)continue;
dep[y]=dep[x]+a[i].w;
dfs(y,x);
rt1[x]=T1.Merge(rt1[x],rt1[y]);
rt2[x]=T2.Merge(rt2[x],rt2[y]);
}
while(rt1[x]&&rt2[x]){
ll X=rt1[x];rt1[x]=T1.Delete(rt1[x]);T1.t[X][0]=T1.t[X][1]=0;
ll Y=rt2[x];rt2[x]=T2.Delete(rt2[x]);T2.t[Y][0]=T2.t[Y][1]=0;
if(T1.w[X]+T2.w[Y]-2*dep[x]<0){
ll A=T1.w[X],B=T2.w[Y];ans+=A+B-2*dep[x];
T1.w[X]=2*dep[x]-B;rt1[x]=T1.Merge(rt1[x],X);
T2.w[Y]=2*dep[x]-A;rt2[x]=T2.Merge(rt2[x],Y);
}
else{
rt1[x]=T1.Merge(rt1[x],X);
rt2[x]=T2.Merge(rt2[x],Y);
break;
}
}
return;
}
signed main()
{
scanf("%lld",&n);
for(ll i=1,x,y,w;i<n;i++){
scanf("%lld%lld%lld",&x,&y,&w);
addl(x,y,w);addl(y,x,w);
}
for(ll i=1;i<=n;i++){
ll x,y;
scanf("%lld%lld",&x,&y);
c[i]=x-y;
if(c[i]<0)ans+=-c[i]*inf;
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2021-02-21 YbtOJ#912-神秘语言【结论,欧拉定理】
2021-02-21 P4542-[ZJOI2011]营救皮卡丘【费用流,Floyd】
2021-02-21 YbtOJ#763-攻城略池【线段树合并】