【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 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

第一问最大流

第二问

建立超级源和超级汇,超级源向1连边,容量为K,n向超级汇连边,容量同上。原来的每条边再建立一条,容量为inf,费用为W,在原图上增广,跑最小费用最大流

但是!!!新边一定要在求完第一问之后再建。。。

代码量略大。。。不过我都上套板子。。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 using namespace std;
  6 const int N=55555,inf=1000000;
  7 struct ee{int to,next,f,w;}e[N*2];
  8 int S,T,cnt=1,n,k,ans1,ans2,timer,m,u[N],v[N],w[N],c[N],mid;
  9 int head[N],dis[N],pre[N],q[N];
 10 bool inq[N],flag=1;
 11 void ins(int u,int v,int f,int w){
 12     e[++cnt].to=v,e[cnt].next=head[u],e[cnt].f=f,e[cnt].w=w,head[u]=cnt;
 13     e[++cnt].to=u,e[cnt].next=head[v],e[cnt].f=0,e[cnt].w=-w,head[v]=cnt;
 14 }
 15 bool spfa(){
 16     for (int i=1;i<=T;i++) dis[i]=inf;
 17     int h=0,t=1;
 18     q[t]=S;dis[S]=0;inq[S]=1;
 19     while (h!=t){
 20         int now=q[++h];if(h==2501) h=0;
 21         for (int i=head[now];i;i=e[i].next){
 22             int v=e[i].to;
 23             if (dis[v]>dis[now]+e[i].w&&e[i].f){
 24                 dis[v]=dis[now]+e[i].w;
 25                 pre[v]=i;
 26                 if (!inq[v]){
 27                     q[++t]=v;if (t==2501) t=0;
 28                     inq[v]=1;
 29                 }
 30             }
 31         }
 32         inq[now]=0;
 33     }
 34     if (dis[T]==inf) return 0;
 35     return 1;
 36 }
 37
 38 void updata(){
 39     int tmp=T,flow=inf;
 40     while (tmp!=S){
 41         int l=pre[tmp],v=e[l].to;
 42         flow=min(flow,e[l].f);
 43         tmp=e[l^1].to;
 44     }
 45     tmp=T;
 46     while (tmp!=S){
 47         int l=pre[tmp],v=e[l].to;
 48         e[l].f-=flow;e[l^1].f+=flow;
 49         tmp=e[l^1].to;
 50     }
 51     mid+=flow;
 52     if(mid>=k) flag=0;
 53     ans2+=dis[T]*flow;
 54 }
 55
 56 bool bfs(){
 57     for (int i=1;i<=T;i++) dis[i]=inf;
 58     int h=0,t=1,now;
 59     q[1]=1;dis[1]=0;
 60     while(h!=t){
 61         now=q[++h];
 62         for (int i=head[now];i;i=e[i].next){
 63             int v=e[i].to;
 64             if (e[i].f&&dis[now]+1<dis[v]){
 65                 dis[v]=dis[now]+1;
 66                 if (v==n)return 1;
 67                 q[++t]=v;
 68             }
 69         }
 70     }
 71     if (dis[n]==inf) return 0; return 1;
 72 }
 73
 74 int dinic(int now,int f){
 75     if (now==n) return f;
 76     int rest=f;
 77     for (int i=head[now];i;i=e[i].next){
 78         int v=e[i].to;
 79         if (e[i].f&&dis[v]==dis[now]+1&&rest){
 80             int t=dinic(v,min(rest,e[i].f));
 81             if (!t) dis[v]=0;
 82             e[i].f-=t;
 83             e[i^1].f+=t;
 84             rest-=t;
 85             //if(t) printf("%d %d %d\n",now,v,e[i].f);
 86         }
 87     }
 88     return f-rest;
 89 }
 90
 91 int main(){
 92     scanf("%d%d%d",&n,&m,&k);
 93     S=0,T=n+1;
 94     for (int i=1;i<=m;i++){
 95         scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]);
 96         ins(u[i],v[i],c[i],0);
 97     }
 98     ins(S,1,k,0);ins(n,T,k,0);
 99     while(bfs())
100     ans1+=dinic(1,inf);
101     for (int i=1;i<=m;i++)ins(u[i],v[i],inf,w[i]);
102     while(flag&&spfa())
103     updata();
104     printf("%d %d",ans1,ans2);
105 }
时间: 2024-10-12 06:47:21

【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 网络扩容

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 网络扩容(费用流)

Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. Solution 先求出最大流maxflow 求最小扩容费用的话,对于每一条边,建一条容量为c费用为0的边,再建一条容量为INF费用为w的边 跑费用流求流入maxflow+k的费用 #include<iostream> #include<cstdio> #include

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 网络扩容(最大流+费用流)

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

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

【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