/**
题目: Fixed Partition Memory Management UVALive - 2238
链接:https://vjudge.net/problem/UVALive-2238
题意:lv
思路:lrjP352.
来自lrj训练指南。

n个程序作为左边结点, n*m个结点在右边;
由于只要求n个程序在右边能找到的匹配点,km算法可以求解。
修改nx,ny的值。
if(f[i][j]==-1){
for(int k = 1; k <= n; k++)
love[i][j*n+k-1] = -INF;///!!!注意这里不能少,相比于左右两边相同节点数的情况,那个时候,love数组所有值都赋值满了。
///而本题右侧节点数更多,所以要自己初始化那些不合法的情况,要不然随机值会影响计算。
continue;
}
*/ #include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
using namespace std;
const int MAXN = ;
const int INF = 0x3f3f3f3f; struct node
{
int st, ed;
int region;
}ans[MAXN];///表示第i个程序,在region区域运行,时间为[st,ed]:
int a[MAXN][MAXN];///a[i][j]表示第i个区域块,倒数第j次运行的程序编号。 int love[MAXN][MAXN]; // 记录每个妹子和每个男生的好感度
int ex_girl[MAXN]; // 每个妹子的期望值
int ex_boy[MAXN]; // 每个男生的期望值
bool vis_girl[MAXN]; // 记录每一轮匹配匹配过的女生
bool vis_boy[MAXN]; // 记录每一轮匹配匹配过的男生
int match[MAXN]; // 记录每个男生匹配到的妹子 如果没有则为-1
int slack[MAXN]; // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
int nx, ny; //左边的为nx个点,右边的为ny个点。
int N; bool dfs(int girl)
{
vis_girl[girl] = true; for (int boy = ; boy < ny; ++boy) { if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次 int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy]; if (gap == ) { // 如果符合要求
vis_boy[boy] = true;
if (match[boy] == - || dfs( match[boy] )) { // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
match[boy] = girl;
return true;
}
} else {
slack[boy] = min(slack[boy], gap); // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
}
} return false;
}
///妹子在左边,男生在右边。
int KM()
{
memset(match, -, sizeof match); // 初始每个男生都没有匹配的女生
memset(ex_boy, , sizeof ex_boy); // 初始每个男生的期望值为0 // 每个女生的初始期望值是与她相连的男生最大的好感度
for (int i = ; i < nx; ++i) {
ex_girl[i] = love[i][];
for (int j = ; j < ny; ++j) {
ex_girl[i] = max(ex_girl[i], love[i][j]);
}
} // 尝试为每一个女生解决归宿问题
for (int i = ; i < nx; ++i) { fill(slack, slack + ny, INF); // 因为要取最小值 初始化为无穷大 while () {
// 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止 // 记录每轮匹配中男生女生是否被尝试匹配过
memset(vis_girl, false, sizeof vis_girl);
memset(vis_boy, false, sizeof vis_boy); if (dfs(i)) break; // 找到归宿 退出 // 如果不能找到 就降低期望值
// 最小可降低的期望值
int d = INF;
for (int j = ; j < ny; ++j)
if (!vis_boy[j]) d = min(d, slack[j]); for (int j = ; j < nx; ++j) {
// 所有访问过的女生降低期望值
if (vis_girl[j]) ex_girl[j] -= d;
}
for(int j = ; j < ny; j++){
// 所有访问过的男生增加期望值
if (vis_boy[j]) ex_boy[j] += d;
// 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
else slack[j] -= d;
} }
} // 匹配完成 求出所有配对的好感度的和
int res = ;
for (int i = ; i < ny; ++i){
if(match[i]!=-)
res += love[ match[i] ][i];
} return res;
}
int region[];
typedef pair<int,int> P;
vector<P> program[MAXN];
int f[MAXN][MAXN];///f[i][j]表示第i个程序在第j个区域块的运行时间,如果为-1说明无法运行。
int main()
{
int n, m;
int cas = ;
while (scanf("%d%d",&m,&n)==) {//N外部变量
if(n==&&m==) break;
nx = n, ny = n*m;
for(int i = ; i < m; i++){
scanf("%d",&region[i]);
}
for(int i = ; i < n; i++) program[i].clear();
for(int i = ; i < n; i++){
int k;
scanf("%d",&k);
int v, t;
for(int j = ; j < k; j++){
scanf("%d%d",&v,&t);///区域大小,时间。
program[i].push_back(P(v,t));
}
}
memset(f, -, sizeof f);
for(int i = ; i < n; i++){
for(int j = ; j < m; j++){
int len = program[i].size();
if(program[i][].first>region[j]) continue;
for(int k = ; k < len; k++){
if(program[i][k].first>region[j]){
f[i][j] = program[i][k-].second;
break;
}
}
if(f[i][j]==-){
f[i][j] = program[i][len-].second;
}
}
} for(int i = ; i < n; i++){///第i个程序
for(int j = ; j < m; j++){///第j个区域块
if(f[i][j]==-){
for(int k = ; k <= n; k++)
love[i][j*n+k-] = -INF;///!!!注意这里不能少,相比于左右两边相同节点数的情况,那个时候,love数组所有值都赋值满了。
///而本题右侧节点数更多,所以要自己初始化那些不合法的情况,要不然随机值会影响计算。
continue;
}
for(int k = ; k <= n; k++){///倒数第k次运行。
love[i][j*n+k-] = -k*f[i][j];
}
}
} int sum = -KM();
memset(a, -, sizeof a);
for(int i = ; i < ny; i++){
if(match[i]==-) continue;
int rg, pg, dao;
rg = i/n;
pg = match[i];
dao = i%n+;
a[rg][dao] = pg;
}
for(int i = ; i < m; i++){
int time = ;
for(int j = n; j >= ; j--){
if(a[i][j]==-) continue;
ans[a[i][j]].region = i;
ans[a[i][j]].st = time;
time += f[a[i][j]][i];
ans[a[i][j]].ed = time;
}
} printf("Case %d\n",cas++);
printf("Average turnaround time = %.2lf\n",1.0*sum/n);
for(int i = ; i < n; i++){
printf("Program %d runs in region %d from %d to %d\n",i+,ans[i].region+,ans[i].st,ans[i].ed);
}
printf("\n");
}
return ;
}

模板转自:http://www.cnblogs.com/wenruo/p/5264235.html

n个程序作为左边结点, n*m个结点在右边;
由于只要求n个程序在右边能找到的匹配点,km算法可以求解。
修改nx,ny的值。 特别注意love[i][j]的初始化,全部自己初始化,不要出现随机值,或者上次的残余值的情况。 if(f[i][j]==-){
for(int k = ; k <= n; k++)
love[i][j*n+k-] = -INF;///!!!注意这里不能少,相比于左右两边相同节点数的情况,那个时候,love数组所有值都赋值满了。
///而本题右侧节点数更多,所以要自己初始化那些不合法的情况,要不然随机值会影响计算。
continue;
} const int MAXN = ;
const int INF = 0x3f3f3f3f; int love[MAXN][MAXN]; // 记录每个妹子和每个男生的好感度
int ex_girl[MAXN]; // 每个妹子的期望值
int ex_boy[MAXN]; // 每个男生的期望值
bool vis_girl[MAXN]; // 记录每一轮匹配匹配过的女生
bool vis_boy[MAXN]; // 记录每一轮匹配匹配过的男生
int match[MAXN]; // 记录每个男生匹配到的妹子 如果没有则为-1
int slack[MAXN]; // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
int nx, ny; //左边的为nx个点,右边的为ny个点。 bool dfs(int girl)
{
vis_girl[girl] = true; for (int boy = ; boy < ny; ++boy) { if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次 int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy]; if (gap == ) { // 如果符合要求
vis_boy[boy] = true;
if (match[boy] == - || dfs( match[boy] )) { // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
match[boy] = girl;
return true;
}
} else {
slack[boy] = min(slack[boy], gap); // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
}
} return false;
}
///妹子在左边,男生在右边。
int KM()
{
memset(match, -, sizeof match); // 初始每个男生都没有匹配的女生
memset(ex_boy, , sizeof ex_boy); // 初始每个男生的期望值为0 // 每个女生的初始期望值是与她相连的男生最大的好感度
for (int i = ; i < nx; ++i) {
ex_girl[i] = love[i][];
for (int j = ; j < ny; ++j) {
ex_girl[i] = max(ex_girl[i], love[i][j]);
}
} // 尝试为每一个女生解决归宿问题
for (int i = ; i < nx; ++i) { fill(slack, slack + ny, INF); // 因为要取最小值 初始化为无穷大 while () {
// 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止 // 记录每轮匹配中男生女生是否被尝试匹配过
memset(vis_girl, false, sizeof vis_girl);
memset(vis_boy, false, sizeof vis_boy); if (dfs(i)) break; // 找到归宿 退出 // 如果不能找到 就降低期望值
// 最小可降低的期望值
int d = INF;
for (int j = ; j < ny; ++j)
if (!vis_boy[j]) d = min(d, slack[j]); for (int j = ; j < nx; ++j) {
// 所有访问过的女生降低期望值
if (vis_girl[j]) ex_girl[j] -= d;
}
for(int j = ; j < ny; j++){
// 所有访问过的男生增加期望值
if (vis_boy[j]) ex_boy[j] += d;
// 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
else slack[j] -= d;
} }
} // 匹配完成 求出所有配对的好感度的和
int res = ;
for (int i = ; i < ny; ++i){
if(match[i]!=-)
res += love[ match[i] ][i];
} return res;
}
int main()
{
int n, m;
int cas = ;
while (scanf("%d%d",&m,&n)==) {//N外部变量
if(n==&&m==) break;
nx = n, ny = n*m;///视具体情况初始化。nx表示左边结点个数,ny表示右边结点个数。
      for(int i = ; i < nx; i++){ ///视具体情况初始化。///视具体情况初始化。///视具体情况初始化。///视具体情况初始化。
        for(int j = ; j < ny; j++){///视具体情况初始化。
          scanf("%d",&love[i][j]);
        }
      }
  int sum = KM();
return ;
}

Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配的更多相关文章

  1. UVALive 2238 Fixed Partition Memory Management 固定分区内存管理(KM算法,变形)

    题意:目前有一部分可用内存,分为m个大小固定的区域.现有n个程序要执行,每个程序在不同大小的内存中运行所需的时间不同,要使运行完所有程序所耗时最少,问每个程序在哪块区域中从什么时间运行到什么时间,以及 ...

  2. UVALive 2238 Fixed Partition Memory Management(二分完美匹配)

    题意:计算机中有一些固定大小的内存,内存越大,处理速度越快.对于一个程序,加入不同的内存空间,处理所需时间不同.现给出m个内存空间,n个程序,对于每个程序程序,有k组数据(s,t),分别表示当程序 i ...

  3. LA2238 Fixed Partition Memory Management

    题目大意: m(m<=10)个内存区域,n(n<=50)个程序.找出一个方案来,使得平均结束时刻尽量小.题目保证有解. 同一个程序运行在不同大小的内存区域内,其运行时间不同.(注意,这里说 ...

  4. [poj 3281]最大流+建图很巧妙

    题目链接:http://poj.org/problem?id=3281 看了kuangbin大佬的思路,还用着kuangbin板子orz   http://www.cnblogs.com/kuangb ...

  5. [ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

    The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Descr ...

  6. hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)

    转载:http://blog.csdn.net/cold__v__moon/article/details/7924269 /* 这道题和方格取数2相似,是在方格取数2的基础上的变形. 方格取数2解法 ...

  7. TTTTTTTTTTTT POJ 2112 奶牛与机器 多重二分匹配 跑最大流 建图很经典!!

    Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 15682   Accepted: 5597 ...

  8. POJ 2049 Finding Nemo bfs 建图很难。。

    Finding Nemo Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 6952   Accepted: 1584 Desc ...

  9. UVALIVE 4970 最小权匹配

    首先贴一下这道题的BNU地址,UVA地址自己找吧. http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=11852 题意:这道题的意思就是,给你N个棋子的 ...

随机推荐

  1. 算法进阶面试题02——BFPRT算法、找出最大/小的K个数、双向队列、生成窗口最大值数组、最大值减最小值小于或等于num的子数组数量、介绍单调栈结构(找出临近的最大数)

    第二课主要介绍第一课余下的BFPRT算法和第二课部分内容 1.BFPRT算法详解与应用 找到第K小或者第K大的数. 普通做法:先通过堆排序然后取,是n*logn的代价. // O(N*logK) pu ...

  2. 漫谈可视化Prefuse(五)

    伴随着前期的基础积累,翻过API,读过一些Demo,总觉得自己已经摸透了Prefuse,小打小闹似乎已经无法满足内心膨胀的自己.还记得儿时看的<武状元苏乞儿>中降龙十八掌最后一张居然是空白 ...

  3. Web大前端面试题-Day5

    1.写一个深度克隆方法(es5)? /** *  深拷贝 * @param {object}fromObj 拷贝的对象 * @param {object}toObj  目标对象 */ function ...

  4. win7查看其它工作组 win7 所有工作组

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha win7 所有工作组 ==== win7  网络 工作组 查找 自身有问题.  多刷新几 ...

  5. 异构无线网络之QOS简介

    QoS(Quality of Service,服务质量)指一个网络能够利用各种基础技术,为指定的网络通信提供更好的服务能力, 是网络的一种安全机制, 是用来解决网络延迟和阻塞等问题的一种技术. 在正常 ...

  6. codeforces895E. Eyes Closed

    题目链接 codeforces895E. Eyes Closed 题解 线段树维护期望和 写出修改两区间的相互影响 就是一个区间修改 emmm考试的代码过不去,这么松的spj都过不去Orz,每次和答案 ...

  7. js签名

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  8. 2016年3月11日Android实习日记

    1.明天删除orthodotics_design_animation_content_gif.gif文件.(已完成) 2. 如何检测内存泄露? A: 可以通过一些性能监测分析工具,如 JProfile ...

  9. Mysql启动失败

    错误提示: 服务名无效 错误原因: mysql服务没有安装. 解决方法: 管理员的权限运行cmd 用dos命令进入到mysql安装目录下再进入到bin目录下 运行mysqld -install命令

  10. 一个成功的Git分支模型

    原文: http://www.juvenxu.com/2010/11/28/a-successful-git-branching-model/ 本文中我会展示一种开发模型,一年前该模型就已经被我用在所 ...