您的位置:首页 > 理论基础 > 计算机网络

BZOJ1834 [ZJOI2010] network 网络扩容

2016-03-20 20:31 459 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1834

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的答案。
就是想学一个费用流模版,交到BZOJ上无限TLE

下载到了数据,发现数据是“错误”的,然后才发现有的是Windows/DOS格式有的是UNIX格式……

然后调,发现程序在读入一半的时候就会崩掉,开调试把我带进了头文件,以为自己遇到了OI生涯最大的玄学

然后在来学校的车上猛然想起自己记录边的数组开小了,maxm打成maxn了……

真是“玄学”,原来是低级错误在作怪……

似乎我也荒废挺久了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define rep(i,l,r) for(int i=l; i<=r; i++)
#define clr(x,y) memset(x,y,sizeof(x))
#define travel(x) for(Edge *p=last[x]; p; p=p->pre)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1010;
const int maxm = 5010;
inline int read(){
int ans = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar())
if (c == '-') f = -1;
for(; isdigit(c); c = getchar())
ans = ans * 10 + c - '0';
return ans * f;
}
struct Edge{
Edge *pre,*rev; int to,cap,cost;
}edge[maxm<<2],*last[maxn],*cur[maxn],*pre[maxn],*pt;
int n,m,k,u[maxm],v[maxm],c[maxm],x,d[maxn],S,T;
bool isin[maxn];
queue <int> q;
inline void init(){
clr(last,0); pt = edge;
}
inline void add(int x,int y,int z,int w){
pt->pre = last[x]; pt->to = y; pt->cap = z; pt->cost = w; last[x] = pt++;
pt->pre = last[y]; pt->to = x; pt->cap = 0; pt->cost = -w; last[y] = pt++;
last[x]->rev = last[y]; last[y]->rev = last[x];
}
bool bfs(){
while (!q.empty()) q.pop();
clr(d,-1); d[S] = 0; q.push(S);
while (!q.empty()){
int now = q.front(); q.pop();
travel(now){
if (p->cap > 0 && d[p->to] == -1){
d[p->to] = d[now] + 1;
q.push(p->to);
if (p->to == T) return 1;
}
}
}
return 0;
}
int dfs(int x,int flow){
if (x == T || (!flow)) return flow; int w = 0;
for(Edge *p = cur[x]; p && w < flow; p = p->pre){
if (d[p->to] == d[x] + 1 && p->cap > 0){
int delta = dfs(p->to,min(p->cap,flow-w));
p->cap -= delta; p->rev->cap += delta; w += delta;
if (p->cap) cur[x] = p;
}
}
if (w < flow) d[x] = -1;
return w;
}
int maxflow(){
int ans = 0;
while (bfs()){
rep(i,1,n) cur[i] = last[i];
ans += dfs(S,0x7fffffff);
}
return ans;
}
bool spfa(){
while (!q.empty()) q.pop();
clr(d,INF); clr(isin,0);
d[S] = 0; isin[S] = 1; q.push(S);
while (!q.empty()){
int now = q.front(); q.pop(); isin[now] = 0;
travel(now){
if (p->cap && d[p->to] > d[now] + p->cost){
d[p->to] = d[now] + p->cost;
pre[p->to] = p;
if (!isin[p->to]){
isin[p->to] = 1; q.push(p->to);
}
}
}
}
return d[T] != INF;
}
int mincost(){
int cost = 0; int x = INF;
while (spfa()){
for(Edge *p = pre[T]; p; p = pre[p->rev->to]) x = min(x,p->cap);
for(Edge *p = pre[T]; p; p = pre[p->rev->to]){
cost += x * p->cost; p->cap -= x; p->rev->cap += x;
}
}
return cost;
}
int main(){
n = read(); m = read(); k = read(); init();
rep(i,1,m){
u[i] = read(); v[i] = read(); x = read(); c[i] = read();
add(u[i],v[i],x,0);
}
S = 1; T = n; printf("%d ",maxflow());
S = 0; T = n + 1;
rep(i,1,m) add(u[i],v[i],INF,c[i]);
add(0,1,k,0); add(n,n+1,k,0);
printf("%d\n",mincost());
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: