zoukankan      html  css  js  c++  java
  • bzoj1834

    1834: [ZJOI2010]network 网络扩容

    Time Limit: 3 Sec  Memory Limit: 64 MB
    Submit: 3382  Solved: 1768
    [Submit][Status][Discuss]

    Description

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

    Input

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

    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
    30%的数据中,N<=100
    100%的数据中,N<=1000,M<=5000,K<=10

     

    第一问:按题目要求建费用为0的边,跑一次最大流

    第二问:新建原点S,S->1费用0容量K,对于每一条原图边u->v,新建一条u->v费用w容量inf的边

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #define ll long long
    #define N 5005
    using namespace std;
    int n,m,k,hd[N],vis[N],d[N],cur[N],w[N<<2],pre[N<<2],a[N<<2],tot=1,ans,flow,cost;
    struct edge{int u,v,next,w,cap,flow;}e[N<<2];
    void adde(int u,int b,int c,int d){
        e[++tot].v=b;e[tot].u=u;e[tot].next=hd[u];
        e[tot].cap=c;e[tot].w=d;e[tot].flow=0;hd[u]=tot;
    }
    queue<int>q;
    bool bfs(){
        memset(vis,0,sizeof(vis));
        q.push(1);d[1]=0;vis[1]=1;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=hd[u];i;i=e[i].next){
                int v=e[i].v;
                if(!vis[v]&&e[i].cap>e[i].flow){
                    vis[v]=1;
                    d[v]=d[u]+1;
                    q.push(v);
                }
            }
        }
        return vis[n];
    }
    
    int dfs(int u,int a){
        if(u==n||!a)return a;
        int flow=0,f;
        for(int& i=cur[u];i;i=e[i].next){
            int v=e[i].v;
            if(d[u]+1==d[v]&&(f=dfs(v,min(e[i].cap-e[i].flow,a)))){
                e[i].flow+=f;
                e[i^1].flow-=f;
                flow+=f;a-=f;
                if(!a)break;
            }
        }
        return flow;
    }
    bool spfa(int s,int t,int &flow,int &cost){
        for(int i=1;i<=t;i++)d[i]=0x3f3f3f3f;
        memset(vis,0,sizeof(vis));
        memset(pre,-1,sizeof(pre));
        q.push(s);vis[s]=1;a[s]=0x3f3f3f3f;d[s]=0;
        while(!q.empty()){
            int u=q.front();q.pop();
            vis[u]=0;
            for(int i=hd[u];i;i=e[i].next){
                int v=e[i].v;
                if(e[i].cap>e[i].flow&&d[v]>d[u]+e[i].w){
                    d[v]=d[u]+e[i].w;
                    pre[v]=i;
                    a[v]=min(e[i].cap-e[i].flow,a[u]);
                    if(!vis[v]){
                        q.push(v);
                        vis[v]=1;
                    }
                    
                }
            }
        }
        if(d[t]==0x3f3f3f3f)return 0;
        flow+=a[t];cost+=d[t]*a[t];
        int u=t;
        while(u!=s){
            e[pre[u]].flow+=a[t];
            e[pre[u]^1].flow-=a[t];
            u=e[pre[u]].u;
        }
        return 1;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            adde(a,b,c,0);w[tot]=d;
            adde(b,a,0,0);w[tot]=d;
        }
        while(bfs()){
            for(int i=1;i<=n;i++)cur[i]=hd[i];
            ans+=dfs(1,0x3f3f3f3f);
        }
        int cnt=tot;
        for(int i=2;i<=cnt;i++){
            int u=e[i].u,v=e[i].v;
            if(e[i].cap>0)adde(u,v,0x3f3f3f3f,w[i]);
            else adde(u,v,0,w[i]);
        }adde(n,n+1,k,0);
        while(spfa(1,n+1,flow,cost));
        printf("%d %d",ans,cost);
        return 0;
    }
  • 相关阅读:
    【Udacity】线性回归方程 Regression
    【Android】Warning :uninstalling will remove the application data!
    【Udacity】数据的差异性:值域、IQR、方差和标准差
    docker部署一个简单的mian.py项目文件
    ubuntu安装goland
    Go 语言变量、常量
    Go 语言数据类型
    linux 之文件重命名
    linux 下新建文件自动加锁的解决办法
    go之linux安装
  • 原文地址:https://www.cnblogs.com/wsy01/p/7927275.html
Copyright © 2011-2022 走看看