【[ZJOI2010]网络扩容】

题目

第一问直接板子敲上去

第二问并不明白直接在残量网络上加边的神仙做法

非常显然我们需要让流量加\(k\),那么我们就使得网络里的总流量为\(maxf+k\),\(maxf\)是第一问求出来的最大流

所以搞一个超级源点,向\(1\)连一条流量是\(maxf+k\)费用是\(0\)的边,之后在原来的图的基础上再给每条边加一条流量为\(inf\),费用为相应费用的边

这样让它自己在里面流就必然会流出来\(maxf+k\)的流量

求出最小费用就好了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define maxn 1005
#define re register
#define LL long long
#define inf 999999999
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    char c=getchar();int x=0;while(c<‘0‘||c>‘9‘) c=getchar();
    while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}
struct E{int v,nxt,w,f;} e[20005];
int d[maxn],vis[maxn],head[maxn];
int n,m,num=1,K,S,T;
int a[5005],b[5005],c[5005],t[5005];
inline void add(int x,int y,int ca,int z){e[++num].v=y;e[num].nxt=head[x];e[num].f=ca,e[num].w=z;head[x]=num;}
inline void C(int x,int y,int ca,int z){add(x,y,ca,z),add(y,x,0,-1*z);}
inline int SPFA()
{
    std::queue<int> q;
    for(re int i=S;i<=T;i++) d[i]=inf,vis[i]=0;
    d[T]=0,vis[T]=1,q.push(T);
    while(!q.empty())
    {
        int k=q.front();q.pop();vis[k]=0;
        for(re int i=head[k];i;i=e[i].nxt)
        if(e[i^1].f&&d[e[i].v]>d[k]+e[i^1].w)
        {
            d[e[i].v]=d[k]+e[i^1].w;
            if(!vis[e[i].v]) vis[e[i].v]=1,q.push(e[i].v);
        }
    }
    return d[S]<inf;
}
int dfs(int x,int now)
{
    if(x==n||!now) return now;
    int flow=0,ff;vis[x]=1;
    for(re int i=head[x];i;i=e[i].nxt)
    if(e[i].f&&!vis[e[i].v]&&d[e[i].v]==d[x]+e[i^1].w)
    {
        ff=dfs(e[i].v,min(e[i].f,now));
        if(ff<=0) continue;
        now-=ff,flow+=ff;
        e[i].f-=ff,e[i^1].f+=ff;
        if(!now) break;
    }
    return flow;
}
int main()
{
    n=read(),m=read(),K=read();S=1,T=n;
    int x,y,ca,z,ans=0,tot=0,Mf=0;
    for(re int i=1;i<=m;i++)
        x=read(),y=read(),ca=read(),z=read(),C(x,y,ca,0),a[i]=x,b[i]=y,c[i]=ca,t[i]=z;
    while(SPFA())
    {
        vis[T]=1;
        while(vis[T])
        {
            for(re int i=S;i<=T;i++) vis[i]=0;
            int F=dfs(S,inf);
            ans+=F;
        }
    }
    printf("%d ",ans);
    num=1,memset(head,0,sizeof(head)),memset(e,0,sizeof(e));
    for(re int i=1;i<=m;i++) C(a[i],b[i],inf,t[i]),C(a[i],b[i],c[i],0);
    S=0,C(S,1,ans+K,0);ans=0;
    while(SPFA())
    {
        vis[T]=1;
        while(vis[T])
        {
            for(re int i=S;i<=T;i++) vis[i]=0;
            int F=dfs(S,inf);
            ans+=F*d[S];
        }
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/asuldb/p/10281691.html

时间: 2024-08-30 10:39:19

【[ZJOI2010]网络扩容】的相关文章

[zjoi2010]网络扩容

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

luogu 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的答案. 利用残余网

[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的答案. 输入输出样例 输入样例#

洛谷 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的答案. 输入输出样例 输入样例#

bzoj1834 ZJOI2010网络扩容(费用流)

给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容费用. 其中\(n \le 1000,m \le 5000,k \le 10\) 网络流题,复杂度都是没用的了.... 第一问就是一个裸的最大流 现在我们考虑第二问QwQ 最小扩容费用,我们是不是可以对于原图中的\(u->v\)的边,添加一条\(u->v\),流量为\(inf\),费用为\(w\)的边,这样就可以实

p2604 [ZJOI2010]网络扩容

传送门 分析 第一问就是最大流 第二问用一个源点向1连一条流量为第一问答案+k的边然后跑费用流即可 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cctype> #include<cmath> #include<cstdlib> #include<

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

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,表示一

C++之路进阶——网络流(网络扩容)

1362 网络扩容 省队选拔赛 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1.  在不扩容的情况下,1到N的最大流: 2.  将1到N的最大流增加K所需的最小扩容费用. 输入描述 Input Description 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含