HDU_3879

由于最终收益=所有可能收益-(损失的收益+架设费用),因此我们可以转而用最小割去求损失的收益与架设费用之和。

在建图的时候源点与用户相连,容量为每个用户带来的收益,架设点与汇点相连,容量为架设每个点所需的费用,之后将用户需要的两个点与该用户相连,容量为INF。建好图之后,左边的流量就代表损失的收益,右边的流量就代表架设费用之和,之后求此图的最小割即可。

#include<string.h>
#include<stdio.h>
#define MAXD 60000
#define MAXM 400000
#define INF 1000000000
int first[MAXD], next[MAXM], v[MAXM], flow[MAXM], e;
int SUM, N, M;
int d[MAXD], q[MAXD], work[MAXD];
void add(int a, int b, int w)
{
flow[e] = w;
v[e] = b;
next[e] = first[a];
first[a] = e;
e ++;
}
void init()
{
int i, j, a, b, w;
SUM = 0;
memset(first, -1, sizeof(first));
e = 0;
for(i = 1; i <= N; i ++)
{
scanf("%d", &w);
add(M + i + 1, 1, w);
add(1, M + i + 1, 0);
}
for(i = 1; i <= M; i ++)
{
scanf("%d%d%d", &a, &b, &w);
SUM += w;
add(0, i + 1, w);
add(i + 1, 0, 0);
add(i + 1, a + M + 1, INF);
add(a + M + 1, i + 1, 0);
add(i + 1, b + M + 1, INF);
add(b + M + 1, i + 1, 0);
}
}
int bfs()
{
int i, j, rear;
memset(d, -1, sizeof(d));
d[0] = 0;
rear = 0;
q[rear ++] = 0;
for(i = 0; i < rear; i ++)
for(j = first[q[i]]; j != -1; j = next[j])
if(flow[j] && d[v[j]] == -1)
{
d[v[j]] = d[q[i]] + 1;
if(v[j] == 1)
return 1;
q[rear ++] = v[j];
}
return 0;
}
int dfs(int cur, int a)
{
if(cur == 1)
return a;
for(int &i = work[cur]; i != -1; i = next[i])
if(flow[i] && d[v[i]] == d[cur] + 1)
if(int t = dfs(v[i], a < flow[i] ? a : flow[i]))
{
flow[i] -= t;
flow[i ^ 1] += t;
return t;
}
return 0;
}
int dinic()
{
int res = 0, t;
while(bfs())
{
memcpy(work, first, sizeof(first));
while(t = dfs(0, INF))
res += t;
}
return res;
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
init();
int res = dinic();
printf("%d\n", SUM - res);
}
return 0;
}


HDU_3879

由于最终收益=所有可能收益-(损失的收益+架设费用),因此我们可以转而用最小割去求损失的收益与架设费用之和。

在建图的时候源点与用户相连,容量为每个用户带来的收益,架设点与汇点相连,容量为架设每个点所需的费用,之后将用户需要的两个点与该用户相连,容量为INF。建好图之后,左边的流量就代表损失的收益,右边的流量就代表架设费用之和,之后求此图的最小割即可。

posted on 2011-10-25 09:43  Staginner  阅读(365)  评论(0编辑  收藏  举报