BZOJ 1449: [JSOI2009]球队收益 最小费用最大流 网络流

https://www.lydsy.com/JudgeOnline/problem.php?id=1449

给每条路加上一个权值,每条路的费用是这条路的流量*权值,求最大流的最小费用。

每次spfa记录一下路径找最短的有流量的路,然后就是普通最大流的操作,反向边加流量什么的,网络流的作用依然是选择。

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

原文地址:https://www.cnblogs.com/137shoebills/p/8862903.html