您的位置:首页 > 移动开发

BZOJ2127 happiness

2014-10-01 22:41 176 查看
很好的网络流题目啦,只不过有点烦,不过这下总算是完全掌握了Dinic的精髓。。。

首先考虑建图:

s --> A 权值为a[A] + sigma(他和四周都选全文科的高兴值) / 2

A --> t 权值为b[A] + sigma(他和四周都选全理科的高兴值) / 2

A <--> B 权值为(同时选文科的高兴值+同时选理科的高兴值) / 2

为了解决精度问题,边权先乘以二,最后结果再除以二即可。

但是不知道为什么是对的。。。在此Orz hzwer,要是没有他的程序我就完蛋了。。。

(p.s. 作死小剧场增强版 我数组d一开始刚好开了d[10002],然后t=10002,死活过不了,查了一下午,我也是醉了%>_<%)

/**************************************************************
Problem: 2127
User: rausen
Language: C++
Result: Accepted
Time:2472 ms
Memory:6900 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <algorithm>

#define rep(i, n) for (int (i) = 1; (i) <= (n); ++(i))
#define REP for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j)
using namespace std;
const int inf = (int) 1e9;

struct edges{
int next, to, f;
} e[500000];

int n, m, ans, tot = 1, s, t;
int first[10005], q[10005], d[10005];
int w[101][101], a[101][101], b[101][101];

inline void add_edge(int x, int y, int z){
e[++tot].next = first[x];
first[x] = tot;
e[tot].to = y;
e[tot].f = z;
}

inline void add_Edge(int x, int y, int z){
add_edge(x, y, z);
add_edge(y, x, 0);
}

void add_Edges(int x, int y, int z){
add_Edge(x, y, z);
add_Edge(y, x, z);
}

bool bfs(){
memset(d, 0, sizeof(d));
q[1] = s, d[s] = 1;
int l = 0, r = 1, x, y;
while (l < r){
++l;
for (x = first[q[l]]; x; x = e[x].next){
y = e[x].to;
if (!d[y] && e[x].f)
q[++r] = y, d[y] = d[q[l]] + 1;
}
}
return d[t];
}

int dinic(int p, int limit){
if (p == t || !limit) return limit;
int x, y, tmp, rest = limit;
for (x = first[p]; x; x = e[x].next){
y = e[x].to;
if (d[y] == d[p] + 1 && e[x].f && rest){
tmp = dinic(y, min(rest, e[x].f));
rest -= tmp;
e[x].f -= tmp, e[x ^ 1].f += tmp;
if (!rest) return limit;
}
}
if (limit == rest) d[p] = 0;
return limit - rest;
}

int Dinic(){
int res = 0, x;
while (bfs())
res += dinic(s, inf);
return res;
}

void make_graph(){
int X;
rep(i, n - 1) rep(j, m){
scanf("%d", &X);
ans += X, a[i][j] += X, a[i + 1][j] += X;
add_Edges(w[i][j], w[i + 1][j], X);
}
rep(i, n - 1) rep(j, m){
scanf("%d", &X);
ans += X, b[i][j] += X, b[i + 1][j] += X;
add_Edges(w[i][j], w[i + 1][j], X);
}
rep(i, n) rep(j, m - 1){
scanf("%d", &X);
ans += X, a[i][j] += X, a[i][j + 1] += X;
add_Edges(w[i][j], w[i][j + 1], X);
}
rep(i, n) rep(j, m - 1){
scanf("%d", &X);
ans += X, b[i][j] += X, b[i][j + 1] += X;
add_Edges(w[i][j], w[i][j + 1], X);
}
s =  n * m + 1, t = s + 1;
REP{
add_Edge(s, w[i][j], a[i][j]);
add_Edge(w[i][j], t, b[i][j]);
}
}

int main(){
scanf("%d%d", &n, &m);
REP{
scanf("%d", a[i] + j);
ans += a[i][j], a[i][j] <<= 1;
}
REP{
scanf("%d", b[i] + j);
ans += b[i][j], b[i][j] <<= 1;
}
REP w[i][j] = (i - 1) * m + j;
make_graph();
printf("%d\n", ans - (Dinic() >> 1));
return 0;
}


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