UVA11419 SAM I AM —— 最小点覆盖 + 输出覆盖点集
题目链接:https://vjudge.net/problem/UVA-11419


题解:
1.二分图匹配之最小点覆盖.:把x坐标和y坐标看成是点, 图中的目标看成是边,所以最终的目的是求出用最少的点,去覆盖掉所有的边。如果在M[x][y]处有目标,则连一条边x-y。接着跑一遍匈牙利算法。
2.除此之外,题目还要求输出最小覆盖点集。可知我们已经求出了最大匹配数,首先我们把所有的覆盖点都落在左边的匹配点上。但是这样做却不能保证所有的边都会被覆盖,因为假设左边有未匹配点,且这些未匹配点与右边的点(是匹配点但不是覆盖点)有边,那么这些边就没有被覆盖了。所以为了覆盖掉所有的边,我们需要把左边的覆盖点转移到右边的点上。
3.可知:从左边的未匹配点开始试找增广路,最终是找不到增广路的,否则最大匹配数就会+1了。所以我们可以得出一个结论:从左边的未匹配点开始遍历(访问过的点就不用再访问了),得到的路径为一棵树,且:路径上的首边必为未匹配边,尾边必为匹配边,且两种边交替出现,且最后一个点必为左边的匹配点(也是我们初始设置的覆盖点)。
4.上个结论有什么用呢?我们可以知道,最后一个覆盖点出现在末端,显然浪费了。所以为了充分利用覆盖点,我们得把覆盖点都放置在里面,且交替出现。所以,我们可以:从左边的未匹配点开始遍历。左边未访问到的点设为覆盖点, 右边访问到的点为覆盖点。
5.由于个人理解得不太到位,且语言表达一团糟,所以也解释得很糟糕。所以呈上一副最简单的图,方便理解:

其中点5 7 9就为初始设定的最小覆盖点集, 4 6 9为最终的覆盖点集。
对匈牙利算法的一些浅薄的认识:
枚举左边的每一个点,以此为出发点,看是否能找到增广路,即是否能找到右边的点为未匹配点,由于起始点也为未匹配点,所以在这条路径上,可以增加一对匹配点,怎么做呢?可知在这条增广路径上,未匹配边比匹配边多一条,所以我们就把未匹配边改为匹配边, 把匹配边改为未匹配边。这样,匹配数就+1了。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
const int INF = 2e9;
const int MOD = 1e9+;
const int MAXN = 1e3+; int uN, vN;
int M[MAXN][MAXN], ulink[MAXN], vlink[MAXN];
bool vis[MAXN], uvis[MAXN], vvis[MAXN]; bool dfs(int u)
{
for(int i = ; i<=vN; i++)
if(M[u][i] && !vis[i])
{
vis[i] = true;
if(vlink[i]==- || dfs(vlink[i]))
{
vlink[i] = u;
ulink[u] = i;
return true;
}
}
return false;
} int hungary()
{
int ret = ;
memset(ulink, -, sizeof(ulink));
memset(vlink, -, sizeof(vlink));
for(int i = ; i<=uN; i++)
{
memset(vis, , sizeof(vis));
if(dfs(i)) ret++;
}
return ret;
} //从左边的未匹配点走一遍试找增广路的路径,但是却不可能找到增广路,否则最大匹配数会增加。
//路径上的首边必为未匹配边,尾边必为匹配边,且两种边交替出现。
void hungary_tree(int u)
{
uvis[u] = true;
for(int i = ; i<=vN; i++)
if(M[u][i] && !vvis[i])
{
vvis[i] = true;
hungary_tree(vlink[i]);
}
} int main()
{
int m;
while(scanf("%d%d%d", &uN, &vN, &m)&& (uN || vN || m))
{
memset(M, false, sizeof(M));
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v); //不能连双向图, 为什么?
M[u][v] = true; //因为u代表横坐标,v代表纵坐标.
} int cnt = hungary();
printf("%d", cnt); memset(uvis, false, sizeof(uvis));
memset(vvis, false, sizeof(vvis));
for(int i = ; i<=uN; i++) if(ulink[i]==-) hungary_tree(i);
for(int i = ; i<=uN; i++) if(!uvis[i]) printf(" r%d", i);
for(int i = ; i<=vN; i++) if(vvis[i]) printf(" c%d", i);
printf("\n");
}
}
UVA11419 SAM I AM —— 最小点覆盖 + 输出覆盖点集的更多相关文章
- hdoj-1068(二分图的最小点覆盖)
题目 1 问题转化: 求二分图最小点覆盖(覆盖所有的边) 2 问题的解决: 二分图最小点覆盖==其最大匹配数 3 证明: 链接 =#include <bits/stdc++.h> ...
- UVa 11419 我是SAM(最小点覆盖+路径输出)
https://vjudge.net/problem/UVA-11419 题意:一个网格里面有一些目标,可以从某一行,某一列发射一发子弹,可以打掉它:求最少的子弹,和在哪里打? 思路: 每个点的x坐标 ...
- UVA-11419 SAM I AM (最小点覆盖)
题目大意:在一个n*m的网格中,有k个目标,现在可以任选一行或列消除在其上的所有目标,求出最少选择次数及选法. 题目分析:经典的最小点覆盖问题,并且输出一个最小点覆盖集.在求出最大匹配之后,以未覆盖的 ...
- UVa11419 SAM I AM(构造最小点覆盖)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27475 [思路] 二分图的最小点覆盖以及构造最小覆盖. 二分图的最 ...
- UVA 11419 SAM I AM(最大二分匹配&最小点覆盖:König定理)
题意:在方格图上打小怪,每次可以清除一整行或一整列的小怪,问最少的步数是多少,又应该在哪些位置操作(对输出顺序没有要求). 分析:最小覆盖问题 这是一种在方格图上建立的模型:令S集表示“行”,T集表示 ...
- UVA 11419 SAM I AM (最小点覆盖,匈牙利算法)
题意:给一个r*c的矩阵,某些格子中可能有一些怪物,可以在一行或一列防止一枚大炮,大炮会扫光整行/列的怪,问最少需要多少炮?输出炮的位置. 思路: 先每行和列都放一个炮,把炮当成点,把怪当成边,一边连 ...
- P2764 最小路径覆盖问题 (最小点覆盖=顶点数-最大匹配)
题意:最小路径覆盖 题解:对于一个有向图,最小点覆盖 = 顶点数 - 最大匹配 这里的最大匹配指的是将原图中每一个点拆成入点.出点, 每条边连接起点的出点和终点的入点 源点S连接每个点的出点,汇点T连 ...
- POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...
- 二分图变种之最小路径覆盖、最小点覆盖集【poj3041】【poj2060】
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=54859604 向大(hei)佬(e)势力学(di ...
随机推荐
- python基础——1(简介与变量)
目录 一.编程语言介绍 1.1.机器语言: 1.2.汇编语言: 1.3.高级语言: 二.安装python解释器 2.1.验证python解释器的安装 2.2.设置环境变量 三.执行python程序的两 ...
- 【MFC】利用MFC写一个计时器小程序
1整体设计 创建对话框程序,并且设计对话框相关控件如图 相应的ID和对应的成员变量如图: 我的想法是这样的,只读属性的编辑框添加有CString类型的成员变量(如s_hour),在xxxDlg.h里另 ...
- Python+selenium(操作隐藏元素)
测试过程中,偶尔会碰到一些页面的隐藏元素,如下,是小编举的一个简单的例子: test.html <html> <head></head> <body> ...
- 让Selenium稳定运行的技巧
Selenium简介 Selenium是非常流行的Web自动化测试工具.它具有自动化测试用例制作简单,支持多种浏览器和不同的操作系统等优点. Selenium脚本不稳定的问题 有很多时候Seleniu ...
- NYOJ90-整数划分,经典递归思想~~
整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk, 其中n1≥n2≥-≥nk≥1,k≥1. 正整数 ...
- BZOJ4552 - [TJOI2016]排序
Portal Description 给出一个\(1..n(n\leq10^5)\)的排列,进行\(m(m\leq10^5)\)次操作: 升序排列\([L,R]\)中的数. 降序排列\([L,R]\) ...
- bzoj 1703 [Usaco2007 奶牛排名 传递闭包
[Usaco2007 Mar]Ranking the Cows 奶牛排名 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 504 Solved: 343[ ...
- [转]android 如何获取第三方app的sha1值
对于android 应用的sha1值和md5值的获取,如果是我们自己的应用,不论是获取测试的和正式的都是比较方便的.但是如何去获取别人开发的app的sha1和md5呢,并且我们只有apk有没有相关的文 ...
- Iptables指南教程收集
iptables对于任何Linux基本都适用,虽然在最新版的CentOS 7和Ubuntu上已经有代替的工具来简化iptables,但是最终还是会把规则写入iptables中. 读教程前先阅读ipta ...
- 微信接入登录功能access_token流程记录
提示:只有认证过的订阅号或者服务号才能获取access_token. 1.app微信登录第一步是,app调起来微信客户端,通过app端的配置,引入一个微信类库, 2.授权成功后,微信会返回你一个cod ...