【bzoj1834】[ZJOI2010]network 网络扩容

来源:互联网 发布:js防水涂料是什么 编辑:程序博客网 时间:2024/05/18 00:12

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 3195  Solved: 1655
[Submit][Status][Discuss]

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

HINT

Source

Day1

[Submit][Status][Discuss]




学习了学习了


首先DINIC跑最大流

然后在原来的残量网络上加边

边的权值为扩容的费用cost,容量为INF

而原边的费用为0


再建一个源点S,把S连向1,费用为0,容量为k


跑一边最小费用最大流就好了


代码:

#include<cstdio>#include<cstring> #include<vector>#include<algorithm>#include<queue>using namespace std;const int max_m = 30100;const int max_n = 1100;const int INF = 2147483647;struct data{int flow,cap,from,to,cost;}e[max_m];queue<int> q;bool vis[max_n],exist[max_n];int dis[max_n],cur[max_n],pre[max_n],a[max_n];vector<int> G[max_n];int from[max_m],to[max_m],cap[max_m],cost[max_m];int tot = -1,n,m,k,ans = 0;inline void add1(int u,int v,int w){e[++tot] = (data){0,w,u,v,0};G[u].push_back(tot);e[++tot] = (data){w,w,v,u,0};G[v].push_back(tot);}inline int getint(){int ret = 0;char c = getchar();while (c < '0' || c > '9') c = getchar();while (c >= '0' && c <= '9')ret = ret * 10 + c - '0',c = getchar();return ret;}inline bool bfs(){memset(dis,0,sizeof(dis));memset(vis,0,sizeof(vis));vis[1] = 1;q.push(1);while (!q.empty()){int u = q.front();q.pop();for (int i = 0; i < G[u].size(); i++){data edge = e[G[u][i]];int v = edge.to;if (vis[v] || edge.flow == edge.cap) continue;dis[v] = dis[u] + 1;vis[v] = 1;q.push(v);}}return vis[n];}inline int dinic(int o,int a){if (o == n || a == 0) return a;int flow = 0;for (int& i = cur[o]; i < G[o].size(); i++){data& edge = e[G[o][i]];int v = edge.to;if (dis[v] != dis[o] + 1) continue; int f = dinic(v,min(a,edge.cap - edge.flow));if (f){edge.flow += f;e[G[o][i] ^ 1].flow -= f;flow += f;a -= f;if (a == 0) break;}}return flow;}inline void add2(int u,int v,int w,int c){e[++tot] = (data){0,w,u,v,c};G[u].push_back(tot);e[++tot] = (data){w,w,v,u,-c};G[v].push_back(tot);}inline bool spfa(){for (int i = 1; i <= n; i++)dis[i] = INF;q.push(0);exist[0] = 1;a[0] = INF;while (!q.empty()){int u = q.front();q.pop();exist[u] = 0;for (int i = 0; i < G[u].size(); i++){data edge = e[G[u][i]];int v = edge.to;if (edge.flow == edge.cap) continue;if (dis[u] + edge.cost < dis[v]){pre[v] = G[u][i];dis[v] = dis[u] + edge.cost;a[v] = min(a[u],edge.cap - edge.flow);if (!exist[v]){exist[v] = 1;q.push(v);}}}}if (dis[n] == INF) return 0;int flow = a[n];ans += a[n] * dis[n];int u = n;while (u != 0){e[pre[u]].flow += flow;e[pre[u] ^ 1].flow -= flow;u = e[pre[u]].from; }return true;}int main(){scanf("%d%d%d",&n,&m,&k);for (int i = 1; i <= m; i++){from[i] = getint(); to[i] = getint(); cap[i] = getint(); cost[i] = getint();add1(from[i],to[i],cap[i]);}int maxflow = 0;while (bfs()){memset(cur,0,sizeof(cur));maxflow += dinic(1,INF);}printf("%d ",maxflow);for (int i = 1; i <= m; i++)add2(from[i],to[i],INF,cost[i]);add1(0,1,k);while (spfa());printf("%d",ans);return 0;}


原创粉丝点击