【BZOJ3322】【洛谷P3280】【SCOI2013】摩托车交易(Kruscal重构树+贪心)
这道题和的那道货车运输有区别吗
做一个重构树就可以了
每次贪心暴力尽量选就是了
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
#define ll long long
const int N=300005;
const ll inf=1000000000000000ll;
int n,m,adj[N],nxt[N<<3],to[N<<3],fa[N<<1],f[N<<1],cnt,dep[N<<1],siz[N<<1],top[N<<1],son[N<<1],tot,q;
int pr[N],fi;
ll b[N],val[N<<1];
struct edge{
int u,v;ll w;
}e[N<<1];
inline bool comp(const edge&a,const edge &b){
return a.w>b.w;
}
inline void addedge(int u,int v) {
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
void dfs1(int u){
siz[u]=1;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u])continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;
if(!son[u])return;
dfs2(son[u],tp);
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
int find(int x){
return f[x]==x?f[x]:f[x]=find(f[x]);
}
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])v=fa[top[v]];
else u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int main(){
tot=n=read(),m=read(),q=read();
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=n;i++)pr[i]=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=1;i<=m;i++){
e[i].u=read(),e[i].v=read(),e[i].w=read();
}
if(q)fi=read();
for(int i=2;i<=q;i++){
e[++m].u=fi,e[m].v=read(),e[m].w=inf;
}
sort(e+1,e+m+1,comp);
for(int i=1;i<=m;i++){
int f1=find(e[i].u),f2=find(e[i].v);
if(f1!=f2){
f[f1]=f[f2]=f[++tot]=tot;
val[tot]=e[i].w;
addedge(f1,tot),addedge(f2,tot);
addedge(tot,f1),addedge(tot,f2);
}
}
dfs1(tot),dfs2(tot,tot);
int plc;ll now=0;
plc=pr[1];
if(b[pr[1]]>0)now=b[pr[1]];
else cout<<0<<'\n';
for(int i=2;i<=n;i++){
now=min(now,val[Lca(pr[i],plc)]);
if(b[pr[i]]>0)now+=b[pr[i]];
else {
b[pr[i]]=-b[pr[i]];
cout<<min(b[pr[i]],now)<<'\n';
now=max(now-b[pr[i]],(ll)0);
}
plc=pr[i];
}
}