http://www.ifrog.cc/acm/problem/1047

思路很简单,跑一发floyd,然后再用km。

但是问题来了,这个有可能n != m。那怎么办?

其实可以补上一些不存在的点。来使得n = m。他们的权值就设置为0就好了。意思就是这些人的搭配,是对答案没有贡献的。注意不能设置为-inf。因为补上的那些点也是必须要选人的,只不过他们选了人,相当于没选而已(权值不存在。)如果设置为-inf的那些,那么他们就会把答案改了。

还有一个小trick的就是,一开始,我是把本来地图上的-1的那些点,更改为inf的,inf表示不连通,那么直接floyd就可以了不用特判那么多。那么问题又来了。如果跑了floyd后,还是不连通,那怎么办?他们的权值可是inf啊。组成新图的时候,同时也是需要把他们的权值设置为0的,也就是相当于没选。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e2 + ;
int e[maxn][maxn];
int TE[ * maxn][ * maxn];
int match[maxn];//match[col] = row
int vx[maxn],vy[maxn];
int fx[maxn],fy[maxn];
int n, m;
int dfs (int u) {
vx[u]=;
int i;
for (i=; i<=m; i++) { //筛选n个 导航员 col的值
if (vy[i]==&&fx[u]+fy[i]==e[u][i]) {
vy[i]=;
if (match[i]==||dfs(match[i])) {
match[i]=u;// match[col]=row;
return ;//搭配成功
}
}
}
return ;//我找不到啊,后面,就会执行km
}
void do_km() { //
int i,j;
int d=inf;
for (i=; i<=n; i++) { //遍历每一个驾驶员 row的值
if (vx[i]==) {
for (j=; j<=m; j++) { //对他进行遍历导航员 col的值
if (!vy[j]) {
if (d>(fx[i]+fy[j]-e[i][j])) {
d=fx[i]+fy[j]-e[i][j];
}
}
}
}
}
for (i=; i<=n; i++) {
if (vx[i]==) {
fx[i] -= d;
vx[i]=;//请0
}
if (vy[i]==) { //
fy[i] += d;
vy[i]=;//情0
}
}
return ;
}
int anskm() {
memset (vx,,sizeof(vx));
memset (vy,,sizeof(vy));
memset (fx,,sizeof(fx));
memset (fy,,sizeof(fy));
memset (match,,sizeof(match));
//km算法的一部分,先初始化fx,fy
for (int i=; i<=n; i++) { //遍历每一个驾驶员 row的值
fy[i]=;
fx[i]= -inf;//无穷小
for (int j=; j<=m; j++) { //遍历每一个导航员 col的值
if (fx[i]<e[i][j]) { //默契值
fx[i]=e[i][j];
}
}
}
for (int i=; i<=n; i++) { //遍历每一个驾驶员 row的值
memset (vx,,sizeof(vx));
memset (vy,,sizeof(vy));
while (!dfs(i)) {//如果他找不到搭配,就实现km算法
do_km();//km完后,还是会对这个想插入的节点进行dfs的,因为他还没搭配嘛
}
// if (t == m) break;
}
int ans=;
for (int i=; i<=m; i++) //遍历导航员,col的值
ans += e[match[i]][i];//输入的row是驾驶员,col是导航员
//match[i]:导航员i和驾驶员match[i]搭配了 match[col]=row;
return ans;
} void work() {
memset(TE, , sizeof TE);
memset(e, , sizeof e);
cin >> n >> m;
for (int i = ; i <= n + m; ++i) {
for (int j = ; j <= n + m; ++j) {
cin >> TE[i][j];
if (TE[i][j] == -) TE[i][j] = inf;
}
}
for (int k = ; k <= n + m; ++k) {
for (int i = ; i <= n + m; ++i) {
for (int j = ; j <= n + m; ++j) {
if (TE[i][j] > TE[i][k] + TE[k][j]) {
TE[i][j] = TE[i][k] + TE[k][j];
}
}
}
}
// for (int i = 1; i <= n + m; ++i) {
// for (int j = 1; j <= n + m; ++j) {
// cout << TE[i][j] << " ";
// }
// cout << endl;
// }
// cout << endl; for (int i = ; i <= n; ++i) {
for (int j = ; j <= m; ++j) {
e[i][j] = TE[i][n + j];
if (e[i][j] == inf) {
e[i][j] = ; //不联通,要用0代替
}
}
}
if (n > m) {
for (int i = ; i <= n; ++i) {
for (int j = m + ; j <= n; ++j) {
e[i][j] = ;
}
}
m = n;
} else if (n < m) {
for (int i = n + ; i <= m; ++i) {
for (int j = ; j <= m; ++j) {
e[i][j] = ;
}
}
n = m;
}
cout << anskm() << endl;
}
int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
IOS;
int t;
cin >> t;
while (t--) work();
return ;
}

1047 - Best couple 好题~的更多相关文章

  1. 【转】POJ百道水题列表

    以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight ...

  2. POJ题目细究

    acm之pku题目分类 对ACM有兴趣的同学们可以看看 DP:  1011   NTA                 简单题  1013   Great Equipment     简单题  102 ...

  3. 1047 Student List for Course ——PAT甲级真题

    1047 Student List for Course Zhejiang University has 40,000 students and provides 2,500 courses. Now ...

  4. 周赛C题 LightOJ 1047 (DP)

    C - C Time Limit:500MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu   Description Th ...

  5. BZOJ 1047 二维单调队列

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 题意:见中文题面 思路:该题是求二维的子矩阵的最大值与最小值的差值尽量小.所以可以考 ...

  6. POJ推荐50题

    此文来自北京邮电大学ACM-ICPC集训队 此50题在本博客均有代码,可以在左侧的搜索框中搜索题号查看代码. 以下是原文: POJ推荐50题1.标记“难”和“稍难”的题目可以看看,思考一下,不做要求, ...

  7. 北大ACM题库习题分类与简介(转载)

    在百度文库上找到的,不知是哪位大牛整理的,真的很不错! zz题 目分类 Posted by fishhead at 2007-01-13 12:44:58.0 -------------------- ...

  8. [NOIP 2014复习]第三章:动态规划——NOIP历届真题回想

    背包型动态规划 1.Wikioi 1047 邮票面值设计 题目描写叙述 Description 给定一个信封,最多仅仅同意粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定全部的邮票数量都 ...

  9. PAT-乙级-1047. 编程团体赛(20)

    1047. 编程团体赛(20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 编程团体赛的规则为:每个参赛队由若 ...

随机推荐

  1. Linux-awk和shell编程初步

    1 awk 格式: awk -选项 '处理' 输入 awk -F : '{print $1}' file -F指定分隔符, 默认是空格 $1 分割后的第一部分 $0 获得所有部分 NF 表示以分隔符分 ...

  2. 在KitKat(Android 4.4.2) 推送网址给手机

    弱者才会回避问题. 最近想把网址推送给手机实现后台下载,打算故技重施,用短信传送然后中断广播的方法实现隐蔽传送.试了半天发现怎么现在拦不住短信了.查了一下才发现原来Android4.4增加了一个安全机 ...

  3. ip策略路由

    ip route 只是基于目的地址的路由选择 ip rule 路由策略,控制路由选择,可根据源地址,源IP等进行路由选择   路由策略由选择符合操作组成 ip rule add   添加策略 ip r ...

  4. UOJ309 UNR #2 排兵布阵

    包含不小于$\sqrt n$列的只有不大于$\sqrt n$行,修改时这些行打标记,否则暴力更新,操作一列的时候暴力更新这些行.合并没啥影响直接搞就是了.更新需要访问位置,感觉必须用哈希表,并不是特别 ...

  5. ​MongoDB复制集相关方法使用(五)

    这里我们把复制集中可用的方法都实验一遍,帮助我们更好地来理解复制集.提前说明这些方法的使用是基于Mongodb3.2版本来的,看这篇文章之前需要先看上一篇文章. 介绍一下复制集可用的相关方法 rs.h ...

  6. C/C++获取Windows系统CPU和内存及硬盘使用情况

    //1.获取Windows系统内存使用率 //windows 内存 使用率 DWORD getWin_MemUsage(){ MEMORYSTATUS ms; ::GlobalMemoryStatus ...

  7. 【Boost】boost库asio详解3——io_service作为work pool

    无论如何使用,都能感觉到使用boost.asio实现服务器,不仅是一件非常轻松的事,而且代码很漂亮,逻辑也相当清晰,这点上很不同于ACE.使用io_service作为处理工作的work pool,可以 ...

  8. linux 中的局部变量、全局变量、shell 变量的总结

    系统局部变量和全局变量  一.变量分类局部变量和环境变量,局部变量只适用于当前shell,而环境变量是全局的,它适用于所有当前shell以及其派生出来的任意子进程,有些变量是用户创建的,其他的则是专用 ...

  9. samba 安装运行

    samba 安装步骤 1.若之前有安装过相关软件包,先卸载之:sudo apt-get autoremove samba samba-commonsudo apt-get autoremove sys ...

  10. Bean的不同配置方式比较与应用场景

    基于XML配置 Bean的定义:           在XML文件中通过<bean>元素定义. Bean的名称:           通过<bean>的id或name属性定义. ...