bzoj1834 ZJOI2010网络扩容(费用流)

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

其中(n le 1000,m le 5000,k le 10)
网络流题,复杂度都是没用的了....

第一问就是一个裸的最大流

现在我们考虑第二问QwQ
最小扩容费用,我们是不是可以对于原图中的(u->v)的边,添加一条(u->v),流量为(inf),费用为(w)的边,这样就可以实现扩容了。可是我们怎么限制最大流增加k呢?

我们可以新建一个t,然后从原来的(t)连向现在的t,费用为0,流量为(maxflow+k)的边,然后直接跑费用流即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
 
using namespace std;
 
inline int read()
{
   int x=0,f=1;char ch=getchar();
   while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
   while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
   return x*f;
}
 
const int maxn = 2018;
const int maxm = 1e6+1e2;
const int inf = 1e9;
 
int n,m,k;
int x[maxm],y[maxm],w[maxm],f[maxm];
int point[maxn],nxt[maxm],to[maxm],cost[maxm],flow[maxm];
int pre[maxm];
int dis[maxn],vis[maxn];
int cnt=1;
int anscost,ansflow;
queue<int> q;
int s,t;
int from[maxn];
 
void addedge(int x,int y,int w,int f)
{
    nxt[++cnt]=point[x];
    to[cnt]=y;
    cost[cnt]=w;
    flow[cnt]=f;
    pre[cnt]=x;
    point[x]=cnt;
}
 
void insert(int x,int y,int w,int f)
{
    addedge(x,y,w,f);
    addedge(y,x,-w,0);
}
 
void init()
{
    cnt=1;
    memset(point,0,sizeof(point));
    memset(dis,127/3,sizeof(dis));
    memset(vis,0,sizeof(vis));
}
 
bool spfa(int s)
{
    memset(dis,127/3,sizeof(dis));
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    dis[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        vis[x]=0;
        for (int i=point[x];i;i=nxt[i])
        {
            int p = to[i];
            if (flow[i]>0 && dis[p]>dis[x]+cost[i])
            {
                from[p]=i;
                dis[p]=dis[x]+cost[i];
                if (!vis[p])
                {
                    q.push(p);
                    vis[p]=1;
                }
            }
        }
    }
    if (dis[t]>=dis[t+1]) return false;
    else return true; 
}
 
void mcf()
{
    int x= inf;
    for (int i=from[t];i;i=from[pre[i]]) x=min(x,flow[i]);
    ansflow+=x;
    for (int i=from[t];i;i=from[pre[i]])
    {
        flow[i]-=x;
        flow[i^1]+=x;
        anscost+=cost[i]*x;
    }
}
 
void solve()
{
    while (spfa(s))
    {
        mcf();
    }
}
int main()
{
  n=read();
  m=read();
  k=read();
  s=1;
  t=n;
  for (int i=1;i<=m;i++) x[i]=read(),y[i]=read(),f[i]=read(),w[i]=read();
  for (int i=1;i<=m;i++) insert(x[i],y[i],0,f[i]);
  solve();
  //cout<<ansflow<<endl;
  int ff=ansflow;
  ansflow=0;anscost=0;
  init();
  for (int i=1;i<=m;i++) insert(x[i],y[i],0,f[i]),insert(x[i],y[i],w[i],inf);
  t=n+1;
  insert(n,n+1,0,ff+k);
  solve();
  cout<<ff<<" "<<anscost;
  return 0;
}
原文地址:https://www.cnblogs.com/yimmortal/p/10160854.html