[BZOJ 1834][ZJOI2010]network 网络扩容(费用流)

Description

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

Solution

先求出最大流maxflow

求最小扩容费用的话,对于每一条边,建一条容量为c费用为0的边,再建一条容量为INF费用为w的边

跑费用流求流入maxflow+k的费用

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int s,t,n,m,k,head[1005],cnt=0,a[1005],dis[1005],pre[1005];
int flow,cost;
bool inq[1005];
int read()
{
    int x=0,f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘){
        if(c==‘-‘)f=-1;c=getchar();
    }
    while(c>=‘0‘&&c<=‘9‘){
        x=x*10+c-‘0‘;c=getchar();
    }
    return x*f;
}
struct Node
{
    int next,from,to,cap,w;
}Edges[20005];
void addedge(int u,int v,int c,int w)
{
    Edges[cnt].next=head[u];
    head[u]=cnt;
    Edges[cnt].from=u;
    Edges[cnt].to=v;
    Edges[cnt].cap=c;
    Edges[cnt].w=w;
    cnt++;
}
void insert(int u,int v,int c,int w)
{
    addedge(u,v,c,w);
    addedge(v,u,0,-w);
}
queue<int>q;
void MCMF(int x)
{
    flow=0,cost=0;
    while(1)
    {
        memset(a,0,sizeof(a));
        memset(dis,0x3f,sizeof(dis));
        q.push(s);
        pre[s]=-1;dis[s]=0,a[s]=x?x-flow:INF,inq[s]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop(),inq[u]=0;
            for(int i=head[u];~i;i=Edges[i].next)
            {
                int v=Edges[i].to;
                if(!x&&Edges[i].cap==INF)continue;
                if(dis[v]>dis[u]+Edges[i].w&&Edges[i].cap>0)
                {
                    dis[v]=dis[u]+Edges[i].w;
                    a[v]=min(a[u],Edges[i].cap);
                    pre[v]=i;
                    if(!inq[v]){q.push(v);inq[v]=1;}

                }
            }
        }
        if(a[t]==0)break;
        flow+=a[t];
        int p=t;
        cost+=a[t]*dis[t];
        while(pre[p]!=-1)
        {
            Edges[pre[p]].cap-=a[t];
            Edges[pre[p]^1].cap+=a[t];
            p=Edges[pre[p]].from;
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read(),m=read(),k=read();
    s=1,t=n;
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read(),c=read(),w=read();
        insert(u,v,c,0);
        insert(u,v,INF,w);
    }
    MCMF(0);
    printf("%d ",flow);
    MCMF(k);
    printf("%d\n",cost);
    return 0;
}
时间: 2024-10-12 06:47:47

[BZOJ 1834][ZJOI2010]network 网络扩容(费用流)的相关文章

bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流

1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. Input 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一

BZOJ 1834 ZJOI2010 network 网络扩容 Dinic+EK费用流

题目大意:给定一个n个点m条边的无向图,每条边有一个扩容费用c,代表每扩容1流量的花费,求最大流及将最大流扩大k的最小费用 第一问直接跑最大流 第二问将每条边的起始点向终点连接一条流量为正无穷.费用为c的边 然后将n向汇点连一条流量为ans+k 费用为0的边 跑最小费用最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 5010 #

bzoj:1834: [ZJOI2010]network 网络扩容

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 Inpu

【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)

我又思考人生了T_T,nd的数组开小了,一直wa,调了一个小时才发现啊!!!!!我一直以为我的isap错了T_T,可是完全没错啊!!!! 这题其实第一个问很简单,跑一次最大流即可.第二个问就是在跑完最大流的残量网络上每条边都扩充容量为oo,费用为边的费用,然后设个超级源连一条容量为k的边到点1,再跑一次费用流即可. 理由很简单,自己想,我就不说了. #include <cstdio> #include <cstring> #include <cmath> #includ

【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边. 输出 输出文件一行包含两个整数,分别表示问题1和问题2的答案. 样例输入 5 8 2 1 2 5 8 2 5 9

[ZJOI2010][bzoj1834] 网络扩容 [费用流]

题面 传送门 思路 第一问:无脑网络流跑一波 第二问: 先考虑一个贪心的结论:扩容出来的扩容流量一定要跑满 证明显然 因此我们可以把扩容费用可以换个角度思考,变成增加一点流量,花费W的费用 这样,我们就得到了一个最小费用流的模型 只要在原图基础上,对于每个原图边,加一条费用为W,无限容量的边,而原图中的所有边费用为0,就可以模拟原题需要的情况了 最后一个问题:流量增加限制K怎么处理? 我们虽然可以用spfa的费用流,一次一次增加,直到K,但是这样也太慢chou了吧? 不怕,我们加一个n+1号点,

1834 [ZJOI2010]network 网络扩容

题解:先在原网络上跑最大流,然后加上带费用的边跑费用流 高一的时候做这道题怎么想不到? 注意:maxn代表的不一定是同一个变量的范围 #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int inf=1000000000; const int maxn=5009; int

BZOJ 1834 ZJOI2010 network 网络扩展 Dinic+EK费用流

标题效果:给定一个n积分m无向图边,每一方有一个扩展的成本c.代表扩张1费用的交通,寻求最大流量和扩大的最大流量k最小成本 第一问直接运行的最大流量 第二个问题将是连接到一个流的末端每个边缘的起点是正无穷大.费用c缘 然后,n汇点被连接到流动ans+k 费用为0的边 跑最小费用最大流就可以 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 5

bzoj1834: [ZJOI2010]network 网络扩容

努力看了很久样例一直过不了...然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了...然后突然想到啊原来的边可以用啊为什么不用...于是A了...感人肺腑 #include<cstdio> #include<cstring> #include<queue> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n