有限制的最小费用最大流 格格取数
来源:互联网 发布:js更改a标签的href 编辑:程序博客网 时间:2024/06/11 04:12
给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要求在矩阵中选择一些数,要求每一行,每一列都至少选到了一个数,使得选出的数的和尽量的小。
这个题目有个限制,不然就非常简单了,每行每列至少选择了一个数,即每行可以多选,这与平常所做的那种简单的最小费用最大流有些不一样。
那么在建图上我们需要做出一些变化
还是那样每行每列都对应一个结点
我们需要强制其每行每列都选择到了数
首先源点向每个行结点连容量为1,花费为-100000的边
每个列结点向汇点连容量为1,花费为-100000的边,
然后行结点跟列结点之间,就连容量为1,花费为相应矩阵中的数值
接着
源点向每个行结点连容量为INF,花费为0的边,
每个列结点向汇点连容量为INF,花费为0的边
这样建图之后,肯定会优先走那些花费为负的边,保证了每一行每一列都选到了点
可以自己画图试试,就可以知道为什么这样可以
然后最后的结果由于多加了一些负数,所以要变化一下
/*ID: CUGB-wwjPROG:LANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define INF 111111#define MAXN 222#define MAXM 55555#define L(x) x<<1#define R(x) x<<1|1#define eps 1e-4using namespace std;struct EDGE{ int v, cap, cost, next, re; // re记录逆边的下标。} edge[MAXM];int n, m, ans, flow, src, des;int e, head[MAXN];int que[MAXN], pre[MAXN], dis[MAXN];bool vis[MAXN];void init(){ e = ans = flow = 0; memset(head, -1, sizeof(head));}void add(int u, int v, int cap, int cost){ edge[e].v = v; edge[e].cap = cap; edge[e].cost = cost; edge[e].next = head[u]; edge[e].re = e + 1; head[u] = e++; edge[e].v = u; edge[e].cap = 0; edge[e].cost = -cost; edge[e].next = head[v]; edge[e].re = e - 1; head[v] = e++;}bool spfa(){ int i, h = 0, t = 1; for(i = 0; i <= n; i ++) { dis[i] = INF; vis[i] = false; } dis[src] = 0; que[0] = src; vis[src] = true; while(t != h) { int u = que[h++]; h %= n; vis[u] = false; for(i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(edge[i].cap && dis[v] > dis[u] + edge[i].cost) { dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]) { vis[v] = true; que[t++] = v; t %= n; } } } } if(dis[des] == INF) return false; return true;}void end(){ int u, p, mi = INF; for(u = des; u != src; u = edge[edge[p].re].v) { p = pre[u]; mi = min(mi, edge[p].cap); } for(u = des; u != src; u = edge[edge[p].re].v) { p = pre[u]; edge[p].cap -= mi; edge[edge[p].re].cap += mi; ans += mi * edge[p].cost; // cost记录的为单位流量费用,必须得乘以流量。 } flow += mi;}int nt;void build(){ scanf("%d%d", &nt, &m); src = nt + m + 1; des = nt + m + 2; n = des; int num; for(int i = 1; i <= nt; i++) for(int j = 1; j <= m; j++) { scanf("%d", &num); add(i, j + nt, 1, num); } for(int i = 1; i <= nt; i++) { add(src, i, 1, -100000); add(src, i, INF, 0); } for(int i = 1; i <= m; i++) { add(i + nt, des, 1, -100000); add(i + nt, des, INF, 0); }}void MCMF(){ init(); build(); while(spfa() && dis[des] < 0) end();}int main(){ int T; int cas = 0; scanf("%d", &T); while(T--) { MCMF(); printf("Case %d: %d\n", ++cas, (nt + m) * 100000 + ans); } return 0;}
0 0
- 有限制的最小费用最大流 格格取数
- 编程之美 2014 格格取数(最小费用最大流)
- poj 2135 有流量限制的最小费用最大流
- poj 3422 有流量限制的最小费用流 反用求最大 + 拆点
- poj 3068 有流量限制的最小费用网络流
- poj 2195 bfs+有流量限制的最小费用流
- 2014 编程之美 预赛第三题 格格取数 上下界费用流
- 有向图的最小费用最大流问题
- wiki 方格取数2 网络流 最大流最小费用流
- codevs 1227 方格取数 2(最小费用最大流)
- POJ 3680 - intervals 一类分配任务,有重叠限制的模型..最大费用最大流..
- [最大费用最大流] [记忆化搜索] [Vijos P1653] 疯狂的方格取数 (getnum)
- 网络流(最大流、最小费用最大流、有上下界的网络流)
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 最小费用最大流
- 【最小费用最大流】
- 2014年10月 西安赛区模板
- 第九周项目二 分数的累加
- 第十章:文件上传下载——深入浅出学Spring Web MVC
- kettle行转列
- java基础--数组(算学生成绩)
- 有限制的最小费用最大流 格格取数
- 1. Nginx的模块与工作原理
- 浅谈光模块之标准接口
- 第九周项目5-程序填充题
- 第十一章:表单标签——深入浅出学Spring Web MVC
- 计算概论A-2-计算机发展以及分类-学习笔记
- 深入理解JVM内存模型
- 小程序
- 设备 酒店 供暖 食品 服装