BZOJ1834 [ZJOI2010] network 网络扩容
题目链接: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了……
真是“玄学”,原来是低级错误在作怪……
似乎我也荒废挺久了
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <queue> 6 #define rep(i,l,r) for(int i=l; i<=r; i++) 7 #define clr(x,y) memset(x,y,sizeof(x)) 8 #define travel(x) for(Edge *p=last[x]; p; p=p->pre) 9 using namespace std; 10 const int INF = 0x3f3f3f3f; 11 const int maxn = 1010; 12 const int maxm = 5010; 13 inline int read(){ 14 int ans = 0, f = 1; 15 char c = getchar(); 16 for(; !isdigit(c); c = getchar()) 17 if (c == '-') f = -1; 18 for(; isdigit(c); c = getchar()) 19 ans = ans * 10 + c - '0'; 20 return ans * f; 21 } 22 struct Edge{ 23 Edge *pre,*rev; int to,cap,cost; 24 }edge[maxm<<2],*last[maxn],*cur[maxn],*pre[maxn],*pt; 25 int n,m,k,u[maxm],v[maxm],c[maxm],x,d[maxn],S,T; 26 bool isin[maxn]; 27 queue <int> q; 28 inline void init(){ 29 clr(last,0); pt = edge; 30 } 31 inline void add(int x,int y,int z,int w){ 32 pt->pre = last[x]; pt->to = y; pt->cap = z; pt->cost = w; last[x] = pt++; 33 pt->pre = last[y]; pt->to = x; pt->cap = 0; pt->cost = -w; last[y] = pt++; 34 last[x]->rev = last[y]; last[y]->rev = last[x]; 35 } 36 bool bfs(){ 37 while (!q.empty()) q.pop(); 38 clr(d,-1); d[S] = 0; q.push(S); 39 while (!q.empty()){ 40 int now = q.front(); q.pop(); 41 travel(now){ 42 if (p->cap > 0 && d[p->to] == -1){ 43 d[p->to] = d[now] + 1; 44 q.push(p->to); 45 if (p->to == T) return 1; 46 } 47 } 48 } 49 return 0; 50 } 51 int dfs(int x,int flow){ 52 if (x == T || (!flow)) return flow; int w = 0; 53 for(Edge *p = cur[x]; p && w < flow; p = p->pre){ 54 if (d[p->to] == d[x] + 1 && p->cap > 0){ 55 int delta = dfs(p->to,min(p->cap,flow-w)); 56 p->cap -= delta; p->rev->cap += delta; w += delta; 57 if (p->cap) cur[x] = p; 58 } 59 } 60 if (w < flow) d[x] = -1; 61 return w; 62 } 63 int maxflow(){ 64 int ans = 0; 65 while (bfs()){ 66 rep(i,1,n) cur[i] = last[i]; 67 ans += dfs(S,0x7fffffff); 68 } 69 return ans; 70 } 71 bool spfa(){ 72 while (!q.empty()) q.pop(); 73 clr(d,INF); clr(isin,0); 74 d[S] = 0; isin[S] = 1; q.push(S); 75 while (!q.empty()){ 76 int now = q.front(); q.pop(); isin[now] = 0; 77 travel(now){ 78 if (p->cap && d[p->to] > d[now] + p->cost){ 79 d[p->to] = d[now] + p->cost; 80 pre[p->to] = p; 81 if (!isin[p->to]){ 82 isin[p->to] = 1; q.push(p->to); 83 } 84 } 85 } 86 } 87 return d[T] != INF; 88 } 89 int mincost(){ 90 int cost = 0; int x = INF; 91 while (spfa()){ 92 for(Edge *p = pre[T]; p; p = pre[p->rev->to]) x = min(x,p->cap); 93 for(Edge *p = pre[T]; p; p = pre[p->rev->to]){ 94 cost += x * p->cost; p->cap -= x; p->rev->cap += x; 95 } 96 } 97 return cost; 98 } 99 int main(){ 100 n = read(); m = read(); k = read(); init(); 101 rep(i,1,m){ 102 u[i] = read(); v[i] = read(); x = read(); c[i] = read(); 103 add(u[i],v[i],x,0); 104 } 105 S = 1; T = n; printf("%d ",maxflow()); 106 S = 0; T = n + 1; 107 rep(i,1,m) add(u[i],v[i],INF,c[i]); 108 add(0,1,k,0); add(n,n+1,k,0); 109 printf("%d\n",mincost()); 110 return 0; 111 }