ACdream-1171 Matrix sum, 最大费用最大流
来源:互联网 发布:wirelessmon mac版 编辑:程序博客网 时间:2024/05/16 23:45
参考:http://blog.csdn.net/yew1eb/article/details/38360253
题目链接:
http://acdream.info/problem?pid=1171
分析:很容易想到二分图模型(n行左端点,m列右端点) --> 有上下界的费用流每行每列取数的个数不能少于R[i] / C[i], 问取得数总和最小是多少Min_Sum? 转化为每行每列取数的个数不多于 m-R[i] / n - C[i],问取得数总和最大是多少Max_Sum?Min_Sum = All_Sum - Max_Sum 总数 - 最大费用最大流即可这样就把有上下界的费用流问题转化为(只有上界)普通的费用流问题了。
心得:注意这个地方的最大费用最大流要掌握原理:
#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<algorithm>using namespace std;const int maxn = 202 + 10;const int INF = 1000000000;typedef long long LL;struct Edge { int from, to, cap, flow, cost;};struct MCMF { //<span style="font-size:14px;">最大费用最大流</span> int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; int inq[maxn]; // 是否在队列中 int d[maxn]; // Bellman-Ford int p[maxn]; // 上一条弧 int a[maxn]; // 可改进量 void init(int n) { this->n = n; for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from, int to, int cap, int cost) { edges.push_back((Edge){from, to, cap, 0, cost}); edges.push_back((Edge){to, from, 0, 0, -cost}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s, int t, LL& ans) { for(int i = 0; i <= t; i++) d[i] = -INF; //与最小费用最大流相反(d[i]=INF) memset(inq, 0, sizeof(inq)); d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; queue<int> Q; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = 0; for(int i = 0; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; if(e.cap > e.flow && d[e.to] < d[u] + e.cost) { <span style="font-family: Arial, Helvetica, sans-serif;">//与最小费用最大流相反(d[e.to] < d[u] + e.cost )</span> d[e.to] = d[u] + e.cost; p[e.to] = G[u][i]; a[e.to] = min(a[u], e.cap - e.flow); if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; } } } } if(d[t] < 0) return false; //<span style="font-family: Arial, Helvetica, sans-serif;">与最小费用最大流相反(d[i]>=0)</span> ans += (LL)d[t] * (LL)a[t]; int u = t; while(u != s) { edges[p[u]].flow += a[t]; edges[p[u]^1].flow -= a[t]; u = edges[p[u]].from; } return true; } // 需要保证初始网络中没有负权圈 LL Mincost(int s, int t) { LL cost = 0; while(BellmanFord(s, t, cost)); return cost; }};MCMF g;int S, T;LL SUM;int a[60][60], R[60], C[60];void init(){ int n, m, i, j; scanf("%d%d", &n, &m); SUM = 0; for(i=1; i<=n; ++i) for(j=1; j<=m; ++j) { scanf("%d", &a[i][j]); SUM += a[i][j]; } for(i=1; i<=n; ++i) scanf("%d", &R[i]); for(i=1; i<=m; ++i) scanf("%d", &C[i]); S = 0, T = n + m + 1; g.init(T); for(i=1; i<=n; ++i) { g.AddEdge(S, i, m-R[i], 0); } for(i=1; i<=m; ++i) { g.AddEdge(i+n, T, n-C[i], 0); } for(i=1; i<=n; ++i) for(j=1; j<=m; ++j) { g.AddEdge(i, j+n, 1, a[i][j]); }}void solve(){ LL t = g.Mincost(S, T); printf("%I64d\n", SUM - t);}int main(){ int T; scanf("%d", &T); while(T--) { init(); solve(); } return 0;}
阅读全文
0 0
- ACdream-1171 Matrix sum, 最大费用最大流
- ACdream-1171 Matrix sum, 最大费用最大流
- [费用流] acdream 1171 Matrix sum
- ACDream 1171 最大费用流,流量不一定最大
- Acdream 1171 Matrix sum 上下界费用流
- ACdream 1171 Matrix sum (有界费用流)
- hdu 2686 Matrix 最大费用最大流
- hdu2686 Matrix 最大费用最大流
- Matrix (hdu 2686 最大费用最大流)
- acdream 1171 Matrix sum
- Kaka's Matrix Travels (最大费用流)
- 【最大费用流】Kaka's Matrix Travels
- hdu 2686 Matrix 最小费用最大流
- hdu 2686 Matrix(最大费用流)
- hdu 2686 Matrix【最大费用流】
- hdu 3376 Matrix Again【最大费用流】
- HDU 2686 Matrix(最大费用流)
- hdu 3376 Matrix Again 最大费用流
- Linux下解压命令大全
- HashMap全面分析及JDK8对HashMap的相关优化
- 为什么matplotlib显示opencv图像不正常
- 文件系统的挂载(NIS NFS Automounter)
- MySQL常用命令
- ACdream-1171 Matrix sum, 最大费用最大流
- SLF4J用户手册
- poj 1065 Wooden Sticks (求最长非降子序列的个数)
- python中的and和or
- fieldset边框样式无效解决方案
- 趣图 | 程序员给小朋友扎辫子
- 所以你根本不想成为一名程序员?
- 两个进度条
- 在Linux环境下mysql的root密码忘记解决方法