poj 2516 Minimum Cost KM算法
来源:互联网 发布:怎么做钓鱼软件 编辑:程序博客网 时间:2024/04/30 13:59
题目链接:http://poj.org/problem?id=2516
之前用费用流做过一次,挺恶心的,各种数组,然后今天又用km做了一遍,更恶心了,不过还好学到了点东西
//km算法中左边点集要少于右边,经过拆点后的商店数一定是少于等于供货点的,所以商店为第一点集,供货点为第二点集#include <iostream>#include <cstdio>#include <cstring>#include <cctype>#include <vector>#include <queue>#include <algorithm>using namespace std;const int N = 100;const int INF = 0x3f3f3f3f;int n, m, k;int need1[N], need2[N];int dian[N][N], supply[N][N];int mpa[N][N][N];int s[N*10][N*10], match[N*10];int nx, ny;int lx[N*10], ly[N*10], slack[N*10];bool visx[N*10], visy[N*10];bool hungary(int v){ visx[v] = true; for(int i = 0; i < ny; i++) { if(visy[i]) continue; if(lx[v] + ly[i] == s[v][i]) { visy[i] = true; if(match[i] == -1 || hungary(match[i])) { match[i] = v; return true; } } else slack[i] = min(slack[i], lx[v] + ly[i] - s[v][i]); } return false;}void km(){ memset(ly, 0, sizeof ly); for(int i = 0; i < nx; i++) lx[i] = -INF; for(int i = 0; i < nx; i++) for(int j = 0; j < ny; j++) lx[i] = max(lx[i], s[i][j]); for(int i = 0; i < nx; i++) { memset(slack, 0x3f, sizeof slack); while(true) { memset(visx, 0, sizeof visx); memset(visy, 0, sizeof visy); if(hungary(i)) break; else { int tmp = INF; for(int j = 0; j < ny; j++) if(! visy[j]) tmp = min(tmp, slack[j]); for(int j = 0; j < nx; j++) if(visx[j]) lx[j] -= tmp; for(int j = 0; j < ny; j++) if(visy[j]) ly[j] += tmp; else slack[j] -= tmp; } } }}int main(){ while(scanf("%d%d%d", &n, &m, &k), n || m || k) { memset(need1, 0, sizeof need1); memset(need2, 0, sizeof need2); for(int i = 0; i < n; i++) for(int j = 0; j < k; j++) { scanf("%d", &dian[i][j]); need1[j] += dian[i][j]; } for(int i = 0; i < m; i++) for(int j = 0; j < k; j++) { scanf("%d", &supply[i][j]); need2[j] += supply[i][j]; } bool f = true; for(int i = 0; i < k; i++) if(need1[i] > need2[i]) { f = false; break; } for(int i = 0; i < k; i++) for(int j = 0; j < n; j++) for(int l = 0; l < m; l++) scanf("%d", &mpa[i][j][l]); if(f == false) { printf("-1\n"); continue; } int res = 0; for(int i = 0; i < k; i++) { memset(match, -1, sizeof match); int tp1[N*10], tp2[N*10]; nx = 0, ny = 0; //拆点,因为km建图连边时无法表示数量,所以要把所有点拆成一个一个的,方式有点小技巧 for(int j = 0; j < n; j++) for(int l = 0; l < dian[j][i]; l++) tp1[nx++] = j; for(int j = 0; j < m; j++) for(int l = 0; l < supply[j][i]; l++) tp2[ny++] = j; for(int j = 0; j < nx; j++) for(int l = 0; l < ny; l++) s[j][l] = -mpa[i][tp1[j]][tp2[l]]; km(); for(int j = 0; j < ny; j++) if(match[j] != -1) res += s[match[j]][j]; } printf("%d\n", -res); } return 0;}
0 0
- poj 2516 Minimum Cost KM算法
- poj 2516 Minimum Cost KM算法 最小权值匹配
- 【原创】【KM算法】POJ 2516 Minimum cost(拆点+多次KM)
- POJ 2516 Minimum Cost(二分图最小权匹配——KM算法)
- POJ 2516 Minimum Cost KM算法 或者 最小费用最大流
- POJ 2516 Minimum Cost (最小费用最大流,KM解法)
- poj 2516 Minimum Cost KM或最小费用流
- poj2516 Minimum Cost 拆点+KM算法
- POJ 2516 Minimum Cost
- Poj 2516 Minimum Cost
- POJ 2516 Minimum Cost
- POJ-2516-Minimum Cost
- poj 2516 Minimum Cost
- POJ 2516 Minimum Cost
- POJ 2516 Minimum Cost
- POJ 2516 Minimum Cost
- POJ 2516 Minimum Cost
- poj 2516 Minimum Cost
- 装饰设计模式(三)demo
- android测试讲解网址
- A - 这是在网吧出的题!!
- 【Unix/Linux编程实践】 动手实现简单的more
- 使用yum源安装CDH Hadoop集群
- poj 2516 Minimum Cost KM算法
- 跨域问题:Access-Control-Allow-Origin
- 数据结构-多项式
- UIDeviceOrientation
- G - sorry 没有北门
- 使用Git+msysGit上传项目
- UEFI BIOS模式下Windows系统启动过程以及引导文件修复方法
- Java基础类库简介及lang包介绍
- 前后台切换会调用哪些方法