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

【bzoj1834】[ZJOI2010]network 网络扩容

2017-06-23 19:46 351 查看

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
;
}

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
== INF) return 0;
int flow = a
;
ans += a
* dis
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: