[BZOJ 2055]80人环游世界 有上下界网络流

来源:互联网 发布:淘宝被骗怎么投诉 编辑:程序博客网 时间:2024/05/01 13:38

由于每一个节点都具体规定了人数,所以上下界一样,然后就像可行流一样建图后跑最小费用最大流就好了.

#include<cstdio>#include<cstring>#include<iostream>#include<queue>#define inf 0x3fffffff#define maxn 205#define maxm 500021using namespace std;int head[maxn],n,m,in[maxn],tot,ans,vis[maxn],fr[maxn],dis[maxn];int S,T,s;queue<int>q;struct edge{int fr,v,next,w,c;}e[maxm];void adde(int a,int b,int x,int y){e[tot]=(edge){a,b,head[a],x,y};head[a]=tot++;e[tot]=(edge){b,a,head[b],0,-y};head[b]=tot++;}bool spfa(){for(int i=S;i<=T;i++)fr[i]=0,dis[i]=1e9,vis[i]=0;q.push(S);dis[S]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int v,i=head[u];i!=-1;i=e[i].next){if(e[i].w&&dis[v=e[i].v]>dis[u]+e[i].c){fr[v]=i;dis[v]=dis[u]+e[i].c;if(!vis[v]){vis[v]=1;q.push(v);}}}}return dis[T]!=1e9;}void solve(){int Min=1e9;for(int x=T;x!=S;x=e[fr[x]].fr){Min=min(Min,e[fr[x]].w);}for(int x=T;x!=S;x=e[fr[x]].fr ){ans+=e[fr[x]].c*Min;e[fr[x]].w-=Min,e[fr[x]^1].w+=Min;}}int main(){memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);S=0,s=2*n+1,T=2*n+2;for(int x,i=1;i<=n;i++){scanf("%d",&x);adde(i,i+n,0,0);in[i]-=x,in[i+n]+=x;}adde(S,s,m,0);for(int i=1;i<=n;i++)adde(s,i,inf,0);for(int i=1;i<=2*n;i++)if(in[i]>0)adde(S,i,in[i],0);else adde(i,T,-in[i],0);for(int i=1;i<=n;i++){for(int j=i+1,x;j<=n;j++){scanf("%d",&x);if(x!=-1)adde(i+n,j,inf,x);}}while(spfa())solve();printf("%d",ans);return 0;}


0 0
原创粉丝点击