您的位置:首页 > 其它

[最大费用可行流 || 单纯形] BZOJ 3118 Orz the MST

2016-09-20 18:27 399 查看
首先很容易根据树边非树边的大小关系列出线性关系

然后对偶一下

可以用线性规划

也可以跑费用流

把对偶后的线性约束写出来 建图就不难看懂了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2){ p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=1005;

struct edge{
int u,v,next; int idx;
}G[N<<1];
int head
,inum;

inline void add(int u,int v,int idx,int p){
G[p].u=u; G[p].v=v; G[p].idx=idx; G[p].next=head[u]; head[u]=p;
}

int n,m;
const int K=21;

int fat
[K],depth
,fad
;
#define V G[p].v
inline void dfs(int u,int fa){
fat[u][0]=fa; depth[u]=depth[fa]+1;
for (int k=1;k<K;k++) fat[u][k]=fat[fat[u][k-1]][k-1];
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),fad[V]=G[p].idx;
}

inline int LCA(int u,int v){
if (depth[u]<depth[v]) swap(u,v);
for (int k=K-1;~k;k--)
if ((depth[u]-depth[v])&(1<<k))
u=fat[u][k];
if (u==v) return u;
for (int k=K-1;~k;k--)
if (fat[u][k]!=fat[v][k])
u=fat[u][k],v=fat[v][k];
return fat[v][0];
}

namespace MCMF{
const int N=1005;
struct edge{
int u,v,w,f,next;
}G[1000005];
int head
,inum=1;
inline void add(int u,int v,int w,int f,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].f=f; G[p].next=head[u]; head[u]=p;
}
inline void link(int u,int v,int w,int f){
add(u,v,w,f,++inum); add(v,u,-w,0,++inum);
}
int S,T;
int dis
,ins
,pre
;
const int NQ=1000005;
#define ad(x) ((x)+1==NQ?(x)=0:++(x))
int Q[NQ],l,r;
int Maxcost;
inline bool SPFA(){
for (int i=1;i<=T;i++) dis[i]=-1<<30,ins[i]=0,pre[i]=0;
l=-1,r=-1;
Q[ad(r)]=S; dis[S]=0; ins[S]=1;
while (l!=r){
int u=Q[ad(l)]; ins[u]=0;
for (int p=head[u];p;p=G[p].next)
if (G[p].f && dis[V]<dis[u]+G[p].w){
dis[V]=dis[u]+G[p].w; pre[V]=p;
if (!ins[V]) Q[ad(r)]=V,ins[V]=1;
}
}
if (dis[T]<=0) return false;
int minimum=1<<30;
for (int p=pre[T];p;p=pre[G[p].u])
minimum=min(minimum,G[p].f);
for (int p=pre[T];p;p=pre[G[p].u]){
G[p].f-=minimum; G[p^1].f+=minimum;
Maxcost+=minimum*G[p].w;
}
return true;
}
inline void Solve(){
while (SPFA());
}
}

int cnt;
int sx
,sy
,sw
,sg
,val
;

int main(){
int ia,ib;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
MCMF::S=m+1; MCMF::T=m+2;
for (int i=1;i<=m;i++){
read(sx[i]); read(sy[i]); read(sw[i]); read(sg[i]); read(ia); read(ib);
if (sg[i]){
add(sx[i],sy[i],i,++inum);
add(sy[i],sx[i],i,++inum);
val[i]=ib;
MCMF::link(MCMF::S,i,0,val[i]);
}else{
val[i]=ia;
MCMF::link(i,MCMF::T,0,val[i]);
}
}
dfs(1,0);
for (int i=1;i<=m;i++)
if (!sg[i]){
int u=sx[i],v=sy[i],lca=LCA(u,v);
while (u!=lca){
if (sw[fad[u]]>sw[i])
MCMF::link(fad[u],i,sw[fad[u]]-sw[i],1<<30);
u=fat[u][0];
}
while (v!=lca){
if (sw[fad[v]]>sw[i])
MCMF::link(fad[v],i,sw[fad[v]]-sw[i],1<<30);
v=fat[v][0];
}
}
MCMF::Solve();
printf("%d\n",MCMF::Maxcost);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: