hdoj 2246 Interesting Housing Problem 【最大费用最大流 or KM算法】
来源:互联网 发布:尘埃3知乎 编辑:程序博客网 时间:2024/09/21 06:38
Interesting Housing Problem
Time Limit: 10000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2726 Accepted Submission(s): 986
Problem Description
For any school, it is hard to find a feasible accommodation plan with every student assigned to a suitable apartment while keeping everyone happy, let alone an optimal one. Recently the president of University ABC, Peterson, is facing a similar problem. While Peterson does not like the idea of delegating the task directly to the class advisors as so many other schools are doing, he still wants to design a creative plan such that no student is assigned to a room he/she dislikes, and the overall quality of the plan should be maximized. Nevertheless, Peterson does not know how this task could be accomplished, so he asks you to solve this so-called "interesting" problem for him.
Suppose that there are N students and M rooms. Each student is asked to rate some rooms (not necessarily all M rooms) by stating how he/she likes the room. The rating can be represented as an integer, positive value meaning that the student consider the room to be of good quality, zero indicating neutral, or negative implying that the student does not like living in the room. Note that you can never assign a student to a room which he/she has not rated, as the absence of rating indicates that the student cannot live in the room for other reasons.
With limited information available, you've decided to simply find an assignment such that every student is assigned to a room he/she has rated, no two students are assigned to the same room, and the sum of rating is maximized while satisfying Peterson's requirement. The question is … what exactly is the answer?
Suppose that there are N students and M rooms. Each student is asked to rate some rooms (not necessarily all M rooms) by stating how he/she likes the room. The rating can be represented as an integer, positive value meaning that the student consider the room to be of good quality, zero indicating neutral, or negative implying that the student does not like living in the room. Note that you can never assign a student to a room which he/she has not rated, as the absence of rating indicates that the student cannot live in the room for other reasons.
With limited information available, you've decided to simply find an assignment such that every student is assigned to a room he/she has rated, no two students are assigned to the same room, and the sum of rating is maximized while satisfying Peterson's requirement. The question is … what exactly is the answer?
Input
There are multiple test cases in the input file. Each test case begins with three integers, N, M, and E (1 <= N <= 500, 0 <= M <= 500, 0 <= E <= min(N * M, 50000)), followed by E lines, each line containing three numbers, Si, Ri, Vi, (0 <= Si < N, 0 <= Ri < M, |Vi| <= 10000), describing the rating Vi given by student Sifor room Ri. It is guaranteed that each student will rate each room at most once.
Each case is followed by one blank line. Input ends with End-of-File.
Each case is followed by one blank line. Input ends with End-of-File.
Output
For each test case, please output one integer, the requested value, on a single line, or -1 if no solution could be found. Use the format as indicated in the sample output.
Sample Input
3 5 50 1 50 2 71 1 61 2 32 4 51 1 10 0 01 1 0
Sample Output
Case 1: 18Case 2: 0Case 3: -1
题意:有N个学生(编号0到N-1)和M个房间(编号0到M-1)。给你E条如(a, b, c)的关系表示学生a对房间b评价为c,当c<0时表示a学生不喜欢b房间,当c为0时表示学生对房间b保持中立态度,当c大于0时表示a学生喜欢房间b。
现在问你存不存在一种方案 保证任意一个学生都不能选上他不喜欢的房间,若存在则输出满足条件的最大评价值之和,若不存在输出-1。
费用流建图:设置超级源点source,超级汇点sink
1,source向所有学生建边,容量为1,费用为0;
2,每个学生向他评价为 喜欢或保持中立的房间建边,容量为1,费用为评价值;
3,所有房间向sink建边,容量为1,费用为0。
费用流1789ms:
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 1010#define MAXM 200000+10#define INF 0x3f3f3f3fusing namespace std;struct Edge{ int from, to, cap, flow, cost, next;};Edge edge[MAXM];int head[MAXN], edgenum;int pre[MAXN], dist[MAXN];bool vis[MAXN];int N, M, E;int source, sink;//超级源点 超级汇点void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w, int c){ Edge E1 = {u, v, w, 0, c, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, -c, head[v]}; edge[edgenum] = E2; head[v] = edgenum++;}void getMap(){ int a, b, c; source = 0, sink = N+M+1; for(int i = 0; i < E; i++) { scanf("%d%d%d", &a, &b, &c); if(c >= 0) addEdge(a+1, b+N+1, 1, c); } for(int i = 1; i <= N; i++) addEdge(source, i, 1, 0); for(int i = 1; i <= M; i++) addEdge(i+N, sink, 1, 0);}bool SPFA(int s, int t){ queue<int> Q; memset(dist, -INF, sizeof(dist)); memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = false; for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(dist[E.to] < dist[u] + E.cost && E.cap > E.flow) { dist[E.to] = dist[u] + E.cost; pre[E.to] = i; if(!vis[E.to]) { vis[E.to] = true; Q.push(E.to); } } } } return pre[t] != -1;}void MCMF(int s, int t, int &cost, int &flow){ cost = flow = 0; while(SPFA(s, t)) { int Min = INF; for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { Edge E = edge[i]; Min = min(Min, E.cap-E.flow); } for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; }}int main(){ int k = 1; while(scanf("%d%d%d", &N, &M, &E) != EOF) { init(); getMap(); int cost, flow; MCMF(source, sink, cost, flow); printf("Case %d: ", k++); if(flow == N) printf("%d\n", cost); else printf("-1\n"); } return 0;}
KM算法:561ms
注意:KM算法 求最大权值匹配时边权赋值为正;求最小权值匹配时边权赋值为负最后取反。
#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 600#define INF 100000000using namespace std;int match[MAXN];int lx[MAXN], ly[MAXN];int slack[MAXN];int Map[MAXN][MAXN];bool visx[MAXN], visy[MAXN];int nx, ny;int DFS(int x){ visx[x] = true; for(int y = 0; y < ny; y++) { if(visy[y]) continue; int t = lx[x] + ly[y] - Map[x][y]; if(t == 0) { visy[y] = true; if(match[y] == -1 || DFS(match[y])) { match[y] = x; return 1; } } else if(slack[y] > t) slack[y] = t; } return 0;}int k = 1;void KM(){ memset(match, -1, sizeof(match)); memset(ly, 0, sizeof(ly)); for(int x = 0; x < nx; x++) { lx[x] = -INF; for(int y = 0; y < ny; y++) { if(Map[x][y] > lx[x]) lx[x] = Map[x][y]; } } for(int x = 0; x < nx; x++) { for(int i = 0; i < ny; i++) slack[i] = INF; while(1) { memset(visx, false, sizeof(visx)); memset(visy, false, sizeof(visy)); if(DFS(x)) break; int d = INF; for(int i = 0; i < ny; i++) { if(!visy[i] && d > slack[i]) d = slack[i]; } for(int i = 0; i < nx; i++) { if(visx[i]) lx[i] -= d; } for(int i = 0; i < ny; i++) { if(visy[i]) ly[i] += d; else slack[i] -= d; } } } //判断是否所有学生都匹配到房间 int res = 0; int num = 0;//匹配数 for(int i = 0; i < ny; i++)//枚举所有人 { if(match[i] != -1 && Map[match[i]][i] != -INF) { num++; res += Map[match[i]][i]; } } printf("Case %d: ", k++); if(num == nx) printf("%d\n", res); else printf("-1\n");}int main(){ int N, M, E; int k = 1; while(scanf("%d%d%d", &N, &M, &E) != EOF) { nx = N; ny = M; for(int i = 0; i < N; i++) for(int j = 0; j < M; j++) Map[i][j] = -INF; int a, b, c; for(int i = 0; i < E; i++) { scanf("%d%d%d", &a, &b, &c); if(c >= 0) { if(c > Map[a][b]) Map[a][b] = c; } } KM(); } return 0;}
0 0
- hdoj 2246 Interesting Housing Problem 【最大费用最大流 or KM算法】
- HDU 2426 Interesting Housing Problem 最小费用最大流 or KM算法
- hdoj--2426--Interesting Housing Problem(最大费用流)
- HDU 2426 Interesting Housing Problem 二分匹配(KM模板)或者最小费用最大流
- POJ 2426 Interesting Housing Problem (最大费用最大流)
- HDU 2426 Interesting Housing Problem【最大费用最大流 && 常规题】
- Interesting Housing Problem----KM
- hdu 2426 Interesting Housing Problem (KM算法)
- hdoj 3488 Tour 【最小费用最大流】【KM算法】
- HDOJ 3315 - My Brute 维护两个最值..构图最大费用最大流 or KM模板
- hdu 2426 Interesting Housing Problem 最大权值 && KM算法
- hdu 2426 Interesting Housing Problem (KM)
- hdu2426 Interesting Housing Problem (KM邻接表)
- hdu 2426 Interesting Housing Problem(KM)
- HDU2426 Interesting Housing Problem(KM匹配 )
- hdu 2426 Interesting Housing Problem【KM】
- POJ 2195 Going Home 最小费用最大流 or KM算法
- hdoj 1853 Cyclic Tour 【最小费用最大流 or KM算法】【构图后可以判断图中是否存在哈密顿环】
- java内存管理和垃圾回收机制
- 《C#入门经典(第6版)》读书笔记3_第三章:变量和表达式
- 虚函数表的实现细节
- hdu 2602 Bone Collector(经典dp)
- [c] poj1008
- hdoj 2246 Interesting Housing Problem 【最大费用最大流 or KM算法】
- linux上安装svn服务
- linux socket网络编程详解
- DataStructure-8.2-平衡二叉树
- Install Jekyll
- 在学习单例模式关于单例数据更新遇到个BUG!(错误)
- git基础使用方法整理
- jquery一些记录(老是搞忘函数用法,规则)
- hive 的一次使用命令