BZOJ2055 80人环游世界 网络流 费用流 有源汇有上下界的费用流

https://darkbzoj.cf/problem/2055 

https://blog.csdn.net/Clove_unique/article/details/54864211 ←对有上下界费用流的处理方法 

首先建立附加源汇ss,tt 
对于原图里有的一条边x->y,[l,r],cost,变成x->y,r-l,cost 
每一个点的权di定义为所有流入这个点的边的下界和-所有流出这个点的边的下界和 
对于一个点i,若di>0,ss->i,di,0;若di<0,i->tt,-di,0 
连边t->s,inf,0 
然后对ss,tt做最小费用最大流 
最终的费用为(网络流中计算的费用+原图中有费用的边的下界*这条边的费用)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=250;
 9 const int minf=10000;
10 int n,m,S,T,SS,mx,ans;
11 struct nod{
12     int x,y,v,co,rev,next;
13 }e[maxn*maxn];
14 int head[maxn]={},tot=0;
15 int dis[maxn]={},fa[maxn]={},vis[maxn]={};
16 inline void init(int x,int y,int v,int co){
17     e[++tot].x=x;e[tot].y=y;e[tot].v=v;e[tot].co=co;e[tot].rev=tot+1;e[tot].next=head[x];head[x]=tot;
18     e[++tot].x=y;e[tot].y=x;e[tot].v=0;e[tot].co=-co;e[tot].rev=tot-1;e[tot].next=head[y];head[y]=tot;
19 }
20 queue<int>q;
21 inline bool SPFA(){
22     memset(dis,31,sizeof(dis));
23     memset(fa,0,sizeof(fa));
24     mx=dis[0];
25     q.push(S);dis[S]=0;
26     while(!q.empty()){
27         int x=q.front();q.pop();vis[x]=0;
28         for(int i=head[x];i;i=e[i].next){
29             int y=e[i].y;
30             if((!e[i].v)||dis[y]<=e[i].co+dis[x])continue;
31             dis[y]=e[i].co+dis[x];fa[y]=i;
32             if(!vis[y]){
33                 q.push(y);vis[y]=1;
34             }
35         }
36     }
37     return dis[T]!=mx;
38 }
39 inline void doit(){
40     int val=mx;
41     for(int i=fa[T];i;i=fa[e[i].x])val=min(val,e[i].v);
42     for(int i=fa[T];i;i=fa[e[i].x]){e[i].v-=val; e[e[i].rev].v+=val; ans+=e[i].co*val;}
43 }
44 int main(){
45     int x;
46     scanf("%d%d",&n,&m);S=n*2+1;T=S+1;SS=T+1;
47     for(int i=1;i<=n;i++){
48         scanf("%d",&x);
49         if(x<=0)continue;
50         init(i,i+n,0,0);
51         init(S,i+n,x,0); init(i,T,x,0);
52     }
53     for(int i=1;i<=n;i++){
54         for(int j=i+1;j<=n;j++){
55             scanf("%d",&x);if(x!=-1)init(i+n,j,minf,x);
56         }
57     }
58     init(S,SS,m,0);
59     for(int i=1;i<=n;i++) init(SS,i,minf,0);
60     ans=0;
61     while(SPFA())doit();
62     printf("%d\n",ans);
63     return 0;
64 }
View Code

 

posted @ 2018-04-26 15:34  鲸头鹳  阅读(216)  评论(0编辑  收藏  举报