P2604 [ZJOI2010]网络扩容

Posted wangyiding2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

思路

有点暴力。先跑一遍dinic,求出第一问的解,再重新建图,讲扩容记为容量inf,费用的边,最后新建t点,容量为maxflow+k,跑最大流最小费用,即可得到ans。

代码

#include<bits/stdc++.h>
#define N 10700
#define M 107000
#define inf 1<<29
using namespace std;
struct node
    int x,y,z,p,next;
e[M*2];
int tot=1,head[N],maxflow=0,ans=0;
int x[M],y[M],z[M],cost[M];
int n,m,s,t,K;
void add(int x,int y,int z,int p)
    e[++tot].y=y;e[tot].z=z;e[tot].p=p;e[tot].next=head[x];head[x]=tot;
    e[++tot].y=x;e[tot].z=0;e[tot].p=-p;e[tot].next=head[y];head[y]=tot;

int incf[N],v[N],pre[N],d[N];
queue<int> q;
bool bfs()
    memset(d,0,sizeof(d));
    while(q.size()) q.pop();
    q.push(s);d[s]=1;
    while(q.size())
        int x=q.front();q.pop();
        for(int i=head[x];i;i=e[i].next)
            int y=e[i].y,z=e[i].z;
            if(z&&!d[y])
                q.push(y);d[y]=d[x]+1;
                if(y==t) return 1;
            
         
    
    return 0;

int dinic(int x,int flow)
    if(x==t) return flow;
    int rest=flow,k;
    for(int i=head[x];i;i=e[i].next)
        int y=e[i].y,z=e[i].z;
        if(z&&d[y]==d[x]+1)
            k=dinic(y,min(rest,z));
            if(!k) d[y]=0;
            e[i].z-=k;
            e[i^1].z+=k;
            rest-=k; 
        
    
    return flow-rest;

bool spfa()
    queue<int> q;
    memset(d,0x3f,sizeof(d));// 0xcf
    memset(v,0,sizeof(v));
    q.push(s);d[s]=0;v[s]=1;
    incf[s]=inf;
    while(q.size())
        int x=q.front();v[x]=0;q.pop();
        for(int i=head[x];i;i=e[i].next)
            int y=e[i].y,z=e[i].z;
            if(!z) continue;
            if(d[y]>d[x]+e[i].p)//d[y]<d[x]+e[i].p
                d[y]=d[x]+e[i].p;
                incf[y]=min(incf[x],z);
                pre[y]=i;
                if(!v[y]) v[y]=1,q.push(y);
            
        
    
    if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf
    return true;

void update()
    int x=t;
    while(x!=s)
        int i=pre[x];
        e[i].z-=incf[t];
        e[i^1].z+=incf[t];
        x=e[i^1].y; 
    
    maxflow+=incf[t];
    ans+=d[t]*incf[t];

void rebuild()
    s=1;t=n+1;
    memset(head,0,sizeof(head));tot=1;
    for(int i=1;i<=m;i++)
        add(x[i],y[i],z[i],0);
        add(x[i],y[i],inf,cost[i]);
    
    add(n,n+1,maxflow+K,0);

int main()

    int flow=0;
    cin>>n>>m>>K;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d%d",&x[i],&y[i],&z[i],&cost[i]);
        add(x[i],y[i],z[i],0);
     s=1;t=n;
    while(bfs()) 
        while(flow=dinic(s,inf)) maxflow+=flow;
    cout<<maxflow<<" ";
    rebuild();
    while(spfa()) update();
    cout<<ans<<endl;
    return 0;

 

以上是关于P2604 [ZJOI2010]网络扩容的主要内容,如果未能解决你的问题,请参考以下文章

P2604 [ZJOI2010]网络扩容

洛谷 P2604 [ZJOI2010]网络扩容

luogu P2604 [ZJOI2010]网络扩容 |费用流

[ZJOI2010]网络扩容

[ZJOI2010]网络扩容

[zjoi2010]网络扩容