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

引用题解:

最大流+费用流。

第一问最大流即可。

第二问为“最小费用最大流”。

由题意,这一问的可转化为在上一问的“残量网络”上,扩大一些边的容量,使能从新的图中的最大流为k。

那么易得:对于还有剩余流量的边,走过他们的费用为0。而“增加流量”可变为:对残留网络上的每一条边建一条容量是∞费用是w的边。这表示从这些边走,每一流量的费用为w,这就符合题意了。

最后建一个超级源点,从超级源向1建一条容量为k,费用为0的边,就可进行最小费用最大流算法

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 1011
#define MAXM 25001
#define INF 2147483647
int S,T,n,m,A[5001],B[5001],W1,Goal;
int en,u[MAXM],W2[5001],v[MAXM],first[MAXN],next[MAXM],cap[MAXM],cost[MAXM];//Next Array
bool inq[MAXN];
int d[MAXN]/*spfa*/,p[MAXN]/*spfa*/,a[MAXN]/*可改进量*/;
queue<int>q;
void Init_MCMF(){memset(first,-1,sizeof(first));en=0;S=1;T=n;}
void AddEdge(const int &U,const int &V,const int &W,const int &C)
{u[en]=U; v[en]=V; cap[en]=W; cost[en]=C; next[en]=first[U]; first[U]=en++;
u[en]=V; v[en]=U; cost[en]=-C; next[en]=first[V]; first[V]=en++;}
bool Spfa(int &Flow,int &Cost)
{
    memset(d,0x7f,sizeof(d));
    memset(inq,0,sizeof(inq));
    d[S]=0; inq[S]=1; p[S]=0; a[S]=INF; q.push(S);
    while(!q.empty())
      {
        int U=q.front(); q.pop(); inq[U]=0;
        for(int i=first[U];i!=-1;i=next[i])
          if(cap[i] && d[v[i]]>d[U]+cost[i])
            {
              d[v[i]]=d[U]+cost[i];
              p[v[i]]=i;
              a[v[i]]=min(a[U],cap[i]);
              if(!inq[v[i]]) {q.push(v[i]); inq[v[i]]=1;}
            }
      }
    if(d[T]>2100000000) return 0;
    Flow+=a[T]; Cost+=d[T]*a[T]; int U=T;
    while(U!=S)
      {
        cap[p[U]]-=a[T]; cap[p[U]^1]+=a[T];
        U=u[p[U]];
      }
    return 1;
}
int Flow,Cost;
int Mincost()
{
    Flow=0,Cost=0;
    while(Spfa(Flow,Cost));
}
int main()
{
	scanf("%d%d%d",&n,&m,&Goal);
	Init_MCMF();
	for(int i=1;i<=m;++i)
	  {
	  	scanf("%d%d%d%d",&A[i],&B[i],&W1,&W2[i]);
	  	AddEdge(A[i],B[i],W1,0);
	  }
	Mincost(); printf("%d ",Flow);
	for(int i=1;i<=m;++i) AddEdge(A[i],B[i],INF,W2[i]);
	S=0; AddEdge(S,1,Goal,0);
	Mincost(); printf("%d\n",Cost);
	return 0;
}

  

时间: 2024-10-12 16:53:22

【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容的相关文章

bzoj1834: [ZJOI2010]network 网络扩容

这道题分为俩步,第一是求最大流,第二是在第一问的残量网络上求最小费用流. 建图时俩个点直接连2条边,一条容量为f[i],费用为0,另一条容量为inf,费用为c[i].这样就可以跑俩个算法了 第二问设一个虚拟源点S与1连容量为k,费用为0的边,n与一个虚拟汇点T连容量为k,费用为0的边.这样一直跑,最后只会增加k的流量. 记住bool一定要用true和false,用0和1tle了..不知道为啥,但一定要记住 #include<cstdio> #include<algorithm> #

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

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

【BZOJ1834】network 网络扩容(最大流,费用流)

题意:给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 30%的数据中,N<=100 100%的数据中,N<=1000,M<=5000,K<=10 思路:RYZ作业 第一问最大流即可 第二问网上很多题解都是在第一问的残余网络上构图,但是根本不需要 考虑边(x,y,z,w) 有容量为z,费用为0的免费流量,有容量为INF,费用为w的扩容付费流

【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

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

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

[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

【BZOJ1834】 [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

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