1834. [ZJOI2010]网络扩容【费用流】

Description

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求: 
1、在不扩容的情况下,1到N的最大流; 
2、将1到N的最大流增加K所需的最小扩容费用。

Input

第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
N<=1000,M<=5000,K<=10

Output

输出文件一行包含两个整数,分别表示问题1和问题2的答案。

Sample Input

5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1

Sample Output

13 19

这个思路非常的妙啊……被宽嫂一语点醒emmm
首先第一问求最大流是裸的问题瞎搞搞就行了……
不过我懒得再写一个Dinic就直接用的费用流跑的最大流
第二问我们将边拆掉
一条为容量为原本容量,费用为0
另一条容量为INF,费用为扩容费用(这意味着这个边可以无限扩容)
然后跑最小费用最大流就好了
那么k如何限定呢?
我们只需要再建立一个新汇点
在原汇点和新汇点间连接一条容量为MaxFlow+k的边,费用为0即可。
趁着宽嫂不注意
STO%%%Cansult%%%OTZ

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<queue>
  6 #define MAXN (5000+10)
  7 #define MAXM (50000+10)
  8 using namespace std; 
  9 queue<int>q;
 10 bool visit[MAXN];
 11 int pre[MAXN];
 12 int n,m,k,s,e,Ans,Fee;
 13 int num_edge;
 14 int head[MAXN];
 15 int dis[MAXN];
 16 bool used[MAXN];
 17 int INF;
 18 struct node
 19 {
 20     int to;
 21     int next;
 22     int Flow;//残留网络 
 23     int Cost;
 24 }edge[MAXM*2];
 25 
 26 void add(int u,int v,int l,int c)
 27 {
 28     edge[++num_edge].to=v;
 29     edge[num_edge].next=head[u];
 30     edge[num_edge].Flow=l;
 31     edge[num_edge].Cost=c;
 32     head[u]=num_edge;    
 33 }
 34 
 35 bool Spfa(int s,int e)
 36 {
 37     memset(pre,-1,sizeof(pre));
 38     memset(dis,0x7f,sizeof(dis));
 39     q.push(s); 
 40     dis[s]=0;
 41     used[s]=true;
 42     while (!q.empty())
 43     {
 44         int x=q.front();
 45         q.pop();
 46         for (int i=head[x];i!=0;i=edge[i].next)
 47             if (dis[x]+edge[i].Cost<dis[edge[i].to] && edge[i].Flow>0)
 48             {
 49                 dis[edge[i].to]=edge[i].Cost+dis[x];
 50                 pre[edge[i].to]=i;
 51                 if (!used[edge[i].to])
 52                 {
 53                     used[edge[i].to]=true;
 54                     q.push(edge[i].to);
 55                 }
 56             }
 57         used[x]=false;
 58     }
 59     return (dis[e]!=INF);
 60 }
 61 
 62 void MCMF(int s,int e)
 63 {
 64     Ans=0,Fee=0;
 65     while (Spfa(s,e))
 66     {
 67         int d=INF;
 68         for (int i=e;i!=s;i=edge[((pre[i]-1)^1)+1].to)
 69             d=min(d,edge[pre[i]].Flow);
 70         for (int i=e;i!=s;i=edge[((pre[i]-1)^1)+1].to)
 71         {
 72             edge[pre[i]].Flow-=d;
 73             edge[((pre[i]-1)^1)+1].Flow+=d;
 74         }
 75         Ans+=d;
 76         Fee+=d*dis[e];
 77     }
 78 }
 79 
 80 int main()
 81 {
 82     int u[MAXM],v[MAXM],l[MAXM],c[MAXM];
 83     memset(&INF,0x7f,sizeof(INF));
 84     scanf("%d%d%d",&n,&m,&k);
 85     
 86     for (int i=1;i<=m;++i)
 87     {
 88         scanf("%d%d%d%d",&u[i],&v[i],&l[i],&c[i]);
 89         add(u[i],v[i],l[i],0);
 90         add(v[i],u[i],0,0);
 91     }
 92     MCMF(1,n);
 93     printf("%d ",Ans);//MaxFlow
 94     
 95     memset(head,0,sizeof(head));
 96     num_edge=0;
 97     
 98     for (int i=1;i<=m;++i)
 99     {
100         add(u[i],v[i],l[i],0);
101         add(v[i],u[i],0,0);
102         add(u[i],v[i],INF,c[i]);
103         add(v[i],u[i],0,-c[i]);
104     }
105     add(n,n+1,Ans+k,0);
106     add(n+1,n,0,0);
107     MCMF(1,n+1);
108     printf("%d",Fee);
109 }
原文地址:https://www.cnblogs.com/refun/p/8678624.html