题解:P10669 BZOJ3118 Orz the MST
太菜了不会线性规划
先分析出一个性质,树边只减小,非树边只增加。然后直接套保序回归。
复杂度不太会分析,但是只跑了 50 ms。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1010,M=6e5+500,inf=1e9;
int S,T,n,m,q[N],q1[N],q2[N],ans[N];
int vis[N];
vector<int>G[N];
bool fg[N];
struct edge{
int a,b,ff,w,u,v;
}len[N];
namespace flow{
int h[N],ne[M],e[M],idx=1,w[M],cnt[N],dis[N],cur[N],tot;
inline void add(int u,int v,ll x1,ll x2){
ne[++idx]=h[u],h[u]=idx,e[idx]=v,w[idx]=x1;
ne[++idx]=h[v],h[v]=idx,e[idx]=u,w[idx]=x2;
}
inline void init(int t1){
tot=t1+2,S=t1+1,T=t1+2;
}
inline int dfs(int u,int sum){
if(u==T) return sum;
int ss=0;
for(int &i=cur[u];i;i=ne[i]){
int v=e[i];
if(w[i]<=0||dis[u]!=dis[v]+1) continue;
int tmp=dfs(v,min(w[i],sum-ss));
ss+=tmp,w[i]-=tmp,w[i^1]+=tmp;
if(sum==ss||dis[S]>=tot) return ss;
}
if(!--cnt[dis[u]]) dis[S]=tot;
++cnt[++dis[u]];
cur[u]=h[u];
return ss;
}
inline void ddd(int u){
fg[u]=1;
for(int i=h[u];i;i=ne[i]){
int v=e[i];
if(w[i]&&!fg[v]) ddd(v);
}
}
inline void work(){
for(int i=1;i<=tot;++i) cur[i]=h[i];
ll res=0;
while(dis[S]<tot) res+=dfs(S,inf);
ddd(S);
idx=1;
memset(h,0,sizeof(int)*(tot+1));
memset(cnt,0,sizeof(int)*(tot+1));
memset(dis,0,sizeof(int)*(tot+1));
}
}
using flow::init;
using flow::work;
ll d[N];
inline void solve(int l,int r,int L,int R){
if(l>r) return ;
if(L==R){
for(int i=l;i<=r;++i) ans[q[i]]=L;
return ;
}
flow::init(r-l+1);
int mid=L+R>>1;
for(int i=l;i<=r;++i) vis[q[i]]=i-l+1;
for(int i=l;i<=r;++i){
d[i]=(len[q[i]].ff?len[q[i]].b:len[q[i]].a)*(abs(mid-len[q[i]].w)-abs(mid+1-len[q[i]].w));
if(d[i]>0) flow::add(S,i-l+1,d[i],0);
else flow::add(i-l+1,T,-d[i],0);
for(int v:G[q[i]]){
if(vis[v]) flow::add(i-l+1,vis[v],inf,0);
}
}
for(int i=l;i<=r;++i) vis[q[i]]=0;
flow::work();
int hh1=0,hh2=0;
for(int i=l;i<=r;++i){
if(!fg[i-l+1]) q1[++hh1]=q[i];
else q2[++hh2]=q[i],fg[i-l+1]=0;
}
fg[r-l+2]=fg[r-l+3]=0;
for(int i=1;i<=hh1;++i) q[l+i-1]=q1[i];
for(int i=1;i<=hh2;++i) q[l+hh1+i-1]=q2[i];
solve(l,l+hh1-1,L,mid),solve(l+hh1,r,mid+1,R);
}
int h[N],ne[N<<1],e[N<<1],w[N<<1],idx=1,fa[N],dep[N];
inline void add(int u,int v,int x){
ne[++idx]=h[u],h[u]=idx,e[idx]=v,w[idx]=x;
ne[++idx]=h[v],h[v]=idx,e[idx]=u,w[idx]=x;
}
inline void dfs(int u){
for(int i=h[u];i;i=ne[i]){
int v=e[i];
if(v!=e[fa[u]]) fa[v]=i^1,dep[v]=dep[u]+1,dfs(v);
}
}
inline void link(int u,int v,int i){
while(u!=v){
if(dep[v]>dep[u]) swap(u,v);
G[w[fa[u]]].push_back(i);
u=e[fa[u]];
}
}
int main(){
scanf("%d%d",&n,&m);
int l=1010,r=0;
for(int i=1;i<=m;++i){
scanf("%d%d%d%d%d%d",&len[i].u,&len[i].v,&len[i].w,&len[i].ff,&len[i].a,&len[i].b);
if(len[i].ff) add(len[i].u,len[i].v,i);
l=min(l,len[i].w);
r=max(r,len[i].w);
q[i]=i;
}
dfs(1);
for(int i=1;i<=m;++i){
if(!len[i].ff) link(len[i].u,len[i].v,i);
}
solve(1,m,l-m,r+m);
ll res=0;
for(int i=1;i<=m;++i){
if(ans[i]<len[i].w) res+=1ll*len[i].b*(len[i].w-ans[i]);
else res+=1ll*len[i].a*(ans[i]-len[i].w);
}
printf("%lld",res);
return 0;
}