hdoj 4307 Matrix 【最大流 求解矩阵乘最值】【经典构图!】
2015-09-06 16:00
429 查看
MatrixTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1573 Accepted Submission(s): 445 Problem Description Let A be a 1*N matrix, and each element of A is either 0 or 1. You are to find such A that maximize D=(A*B-C)*AT, where B is a given N*N matrix whose elements are non-negative, C is a given 1*N matrix whose elements are also non-negative, and AT is the transposition of A (i.e. a N*1 matrix). Input The first line contains the number of test cases T, followed by T test cases. For each case, the first line contains an integer N (1<=N<=1000). The next N lines, each of which contains N integers, illustrating the matrix B. The jth integer on the ith line is B[i][j]. Then one line followed, containing N integers, describing the matrix C, the ith one for C[i]. You may assume that sum{B[i][j]} < 2^31, and sum{C[i]} < 2^31. Output For each case, output the the maximum D you may get. Sample Input 1 3 1 2 1 3 1 0 1 2 3 2 3 7 Sample Output 2 HintFor sample, A=[1, 1, 0] or A=[1, 1, 1] would get the maximum D. |
题意:给出公式【D】 = (【A】 * 【B】 - 【C】)* 【AT】。
其中【B】是一个N*N的矩阵,【C】是一个1*N的矩阵,题中均以给出。
【A】是一个1*N的矩阵且里面元素只有0和1,【AT】是矩阵【A】的变化,是一个N*1的矩阵。
现在让你找到一个【A】使得最后结果最大,并输出最大结果。
ORZ大牛
转自:原文出处
从本质上讲,之所以能够用最大流解决这个问题,关键在于最大流可以求解下面这个函数的最小值:
接下来就分析一下如何用最大流求解上面这个函数的极值。
首先xi一共只有两种选择,那么最终可以按xi的取值将xi划分成两个集合,那么如果xi在值为1的集合里,xj在值为0的集合里,那么就会产生一个代价cij。同时如果xi选择0就会产生一个bi的代价,如果xi选择1就会产生一个ai的代价。
于是构造一个源点S,汇点T做最小割,不妨假设做完最小割之后值为1的xi的集合是和S相连的部分,值为0的xi的集合是和T相连的部分。
由于表达式中有三项,我们用三种割边来分别描述这三项的值。一种是xi选择了1,这样就不能选择0,需要把xi-T这条边割掉,由于xi选择1会产生ai的代价,那么就把这条边的容量设为ai。另一种是xi选择了0,这样就不能选择1,需要把S-xi这条边割掉,由于xi选择0会产生bi的代价,那么就把这条边的容量设为bi。最后一种是xi选择了1,xj选择了0,这样xi和xj不能在同一个集合中,需要把xi-xj这条边割掉,由于xi选择1,xj选择0产生cij的代价,那么就把这条边的容量设为cij。
这样对建好的图做最小割就可以得到上面哪个函数的最小值。
接着我们分析这个题目如何转化成上面这种模型。
首先我们将D的表达式赤裸裸地写出来:
这种形式必然不能看出来和上面那个表达式有什么关系,于是我们继续将其化简:
如果令f等于最后一行括号里的内容,那么发生了什么?如果ai选择0会产生sum{bij}(1<=j<=N)的代价,如果ai选择1会产生ci的代价,如果ai选择1且aj选择0就会产生bij的代价。这样就完全转化成了上面的模型,具体的做法就不再重复说明了。
AC代码:
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> #define MAXN 1010 #define MAXM 3000000 #define INF 0x3f3f3f3f using namespace std; struct Edge { int from, to, cap, flow, next; }; Edge edge[MAXM]; int head[MAXN], edgenum; int dist[MAXN], cur[MAXN]; bool vis[MAXN]; int N; void init() { edgenum = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int w) { Edge E1 = {u, v, w, 0, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, head[v]}; edge[edgenum] = E2; head[v] = edgenum++; } int sum;//记录矩阵B中所有元素之和 int source, sink; void getMap() { init(); scanf("%d", &N); int a; sum = 0; source = 0, sink = N+1; //B矩阵 构图 for(int i = 1; i <= N; i++) { int sumcul = 0; for(int j = 1; j <= N; j++) { scanf("%d", &a); sumcul += a; sum += a; addEdge(i, j, a); } addEdge(source, i, sumcul); } //C矩阵 构图 for(int i = 1; i <= N; i++) { scanf("%d", &a); addEdge(i, sink, a); } } bool BFS(int s, int t) { queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap > E.flow) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false; } int DFS(int x, int a, int t) { if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap-E.flow), t)) > 0) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { int flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, INF, t); } return flow; } int main() { int t; scanf("%d", &t); while(t--) { getMap(); printf("%d\n", sum - Maxflow(source, sink)); } return 0; }
相关文章推荐
- 三分钟理解“状态模式”——设计模式轻松掌握
- 工作周报053
- 原生js实现 返回顶部
- IP地址查询接口
- 婚纱抠图
- Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用
- 250法则
- sql查询上一条数据和下一条数据
- jquery浮动定位层导航描点上下滚动的浮动导航
- 《深入理解计算机系统》读书笔记4---异常控制流
- CSU 1660 K-Cycle
- Nasm Assambly Intro - Compile error
- android调用matlab中的函数方法
- 【树形背包】【JSOI 2008】【bzoj 1017】魔兽地图DotR
- Regionals 2014 >> South Pacific
- 链表中插入和删除结点
- phpexcel读取输出操作
- 第三方登录开发-Facebook
- 关于SparkMLlib的基础数据结构 Spark-MLlib-Basics
- 转:利用ant与jmeter实现负载测试自动化