• 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;
    }
    
  • 相关阅读:
    [转]AsyncTask的用法
    [转]Android Service学习之本地服务
    强制页面运行于IE8模式下
    标签分类
    获取元素的文本
    遍历节点的API
    为IE的javascript提速
    我的选择器 获得经过标记的没有重复的tagName等于tag的元素集
    kangax 的javascript谜题
    自动执行函数
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160854.html
Copyright © 2020-2023  润新知