zoukankan      html  css  js  c++  java
  • 洛谷 P2604 [ZJOI2010]网络扩容

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    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
    输出样例#1:
    13 19
    

    说明

    30%的数据中,N<=100

    100%的数据中,N<=1000,M<=5000,K<=10

    第一问 任何费用为0,流量为给定流量的最大流

    第二问 源点到第一个点流量为k 其他流量为inf ,费用为给定费用的费用流

    屠龙宝刀点击就送

    #include <cstring>
    #include <ctype.h>
    #include <cstdio>
    #include <queue>
    #define M 50005
    #define inf 0x7fffffff
    
    using namespace std;
    void read(int &x)
    {
        x=0;bool f=0;
        register char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        x=f?(~x)+1:x;
    }
    struct Edge
    {
        int next,to,flow,value;
        Edge(int next=0,int to=0,int flow=0,int value=0) :next(next),to(to),flow(flow),value(value) {}
    }edge[M<<1];
    bool vis[M<<1];
    int u[M],v[M],c[M],w[M],n,m,k,dep[M<<1],dis[M<<1],fa[M<<1],flow[M<<1],head[M<<1],cnt=1;
    void insert(int u,int v,int w,int l)
    {
        edge[++cnt]=Edge(head[u],v,w,l);
        head[u]=cnt;
    }
    bool bfs(int s,int t)
    {
        memset(dep,-1,sizeof(dep));
        dep[s]=0;
        queue<int>Q;
        Q.push(s);
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            for(int i=head[now];i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dep[v]==-1&&edge[i].flow>0)
                {
                    dep[v]=dep[now]+1;
                    if(v==t) return true;
                    Q.push(v); 
                }
            }
        }
        return false;
    }
    int min(int a,int b) {return a>b?b:a;} 
    int dfs(int now,int t,int came_flow)
    {
        if(now==t||came_flow==0) return came_flow;
        int f,res=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]==dep[now]+1&&edge[i].flow>0&&(f=dfs(v,t,min(came_flow,edge[i].flow))))
            {
                res+=f;
                came_flow-=f;
                edge[i].flow-=f;
                edge[i^1].flow+=f;
                if(came_flow==0) break;
            }
        }
        if(res!=came_flow) dep[now]=-1;
        return res;
    }
    bool spfa(int s,int t)
    {
        for(int i=s;i<=t;i++) {flow[i]=inf;dis[i]=inf;vis[i]=0;}
        vis[s]=1;
        fa[s]=0;
        dis[s]=0;
        queue<int>Q;
        Q.push(s);
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            vis[now]=0;
            for(int i=head[now];i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dis[v]>dis[now]+edge[i].value&&edge[i].flow>0)
                {
                    dis[v]=dis[now]+edge[i].value;
                    flow[v]=min(flow[now],edge[i].flow);
                    fa[v]=i;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        Q.push(v);
                    }
                }
            }
        }
        return dis[t]<inf;
    }
    int update(int s,int t)
    {
        int x=flow[t];
        for(int i=t;i!=s&&i;i=edge[fa[i]^1].to)
        {
            edge[fa[i]].flow-=x;
            edge[fa[i]^1].flow+=x;
        }
        return dis[t]*x;
    }
    int dinic(int s,int t,int type)
    {
        int ans=0;
        if(type==1)
            for(;bfs(s,t);ans+=dfs(s,t,inf));
        else for(;spfa(s,t);ans+=update(s,t));
        return ans;
    }
    int main()
    {
        read(n);
        read(m);
        read(k);
        for(int i=1;i<=m;i++)
        {
            read(u[i]);
            read(v[i]);
            read(c[i]);
            read(w[i]);
            insert(u[i],v[i],c[i],0);
            insert(v[i],u[i],0,0);
        }
        printf("%d ",dinic(1,n,1));
        for(int i=1;i<=m;i++)
        {
            insert(u[i],v[i],inf,w[i]);
            insert(v[i],u[i],0,-w[i]);
        }
        insert(0,1,k,0);
        insert(1,0,0,0);
        printf("%d
    ",dinic(0,n,2));
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    【模板】并查集
    排队布局
    list
    js获取宽度
    js获取按键
    sublime 自定义快捷代码
    file
    git add Untracked files
    git branch
    git
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7223720.html
Copyright © 2011-2022 走看看