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,死活过不了,查了一下午,我也是醉了%>_<%)
View Code
首先考虑建图:
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
相关文章推荐
- bzoj2127: happiness 最小割
- bzoj2127: happiness 浅析一类最小割问题——二元关系的应用
- bzoj2127: happiness
- bzoj2127: happiness
- bzoj2127 happiness(最小割)
- BZOJ2127: happiness
- BZOJ2127:happiness(最小割)
- bzoj2127 happiness
- BZOJ2127: happiness
- BZOJ2127: happiness
- bzoj2127 happiness 最小割
- bzoj2127 happiness
- bzoj2127: happiness(最小割)
- sucess==happiness
- Happiness Is A Journey
- Happiness wellbeing
- [BZOJ]2127: happiness 最小割
- 2127: happiness 最小割
- 【JZOJ 1919】happiness
- My Happiness is All 分锅记录