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;
}
原文地址:https://www.cnblogs.com/wsy01/p/7927275.html