刚开始看到这个题目的时候就觉得想法很明了,就是不知道如何去匹配...

去网上看了不少人的解题报告,但是对于刚接触“最小边覆盖”的我来说....还是很困难滴....于是自己又开始一如以往学习“最大独立集”、“最小点覆盖的”的思考方式啦:在了解一个看似高深的知识点之前,粗略了解这是个什么东东,那么看概念也会更好理解,(希望此博客在自己以后回头来看会一目明了,也对刚接触“最小边覆盖”的人有帮助(万分感到荣幸)):

首先把题目的第一个案例图形化(第一,图形好理解,第二,很多人看到文字就烦啦。第三,图论不画图怎么可以捏),我们把交叉路看成点,街道看成边,就如下图:

要求选择最少的伞兵降落在某些交叉口,使他们走完所有的交叉口,(注意是单向边)从图中很容易选择,我们在二号交叉口降落一个走到3再走到4,然后在1好交叉口降落一个,总共两个就可以访问所有的交叉口,我们就可以这样看:把3号街道和1号街道看做一条边,把2.3.4号交叉点都覆盖啦:如图

这样就对“最小边覆盖”有了那么点粗俗的理解啦

接下来是解决这个问题,用匈牙利匹配:因为刚开始接触二分匹配,我就想用街道(简化为点)去和交叉口匹配:(谁知道...如图)

可想而知..完全不知道怎么匹配....

接着就看看最小边覆盖和二分匹配的关系吧:(如果觉得看文字概念还是很烦..可以看下面的图形说明,不过结合文字和图形更有助理解)(摘自百度百科)

路径覆盖与
二分图匹配的关系(必须是没有圈的有向图):
最小路径覆盖=|P|-最大匹配数(|P|为定点数)
其中最大匹配数的求法是把P中的每个顶点pi分成两个顶点pi'与pj'',如果在p中存在一条pi到pj的边,那么在二分图P'中就有一条连接pi'与pj''的无向边;这里pi' 就是p中pi的出边,pj''就是p中pj 的一条入边;
对于
公式:最小路径覆盖=|P|-最大匹配数;可以这么来理解;
如果匹配数为零,那么P中不存在有向边,于是显然有:
最小路径覆盖=|P|-最大匹配数=|P|-0=|P|;即P的最小路径覆盖数为|P|;
P'中不在于匹配边时,路径覆盖数为|P|;
如果在P'中增加一条匹配边pi'-->pj'',那么在图P的路径覆盖中就存在一条由pi连接pj的边,也就是说pi与pj 在一条路径上,于是路径覆盖数就可以减少一个;
如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;直到匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面的公式;但是这里只 是说明了每条匹配边对应于路径覆盖中的一条路径上的一条连接两个点之间的有向边;下面来说明一个路径覆盖中的每条连接两个顶点之间的有向边对应于一条匹配 边;
与前面类似,对于路径覆盖中的每条连接两个顶点之间的每条有向边pi--->pj,我们可以在匹配图中对应做一条连接pi'与pj''的边, 显然这样做出来图的是一个匹配图(这一点用反证法很容易证明,如果得到的图不是一个匹配图,那么这个图中必定存在这样两条边 pi'---pj'' 及 pi' ----pk'',(j!=k),那么在路径覆盖图中就存在了两条边pi-->pj, pi--->pk ,那边从pi出发的路径就不止一条了,这与路径覆盖图是矛盾的;还有另外一种情况就是存在pi'---pj'',pk'---pj'',这种情况也类似可证);
至此,就说明了匹配边与路径覆盖图中连接两顶点之间边的一一对应关系,那么也就说明了前面的公式成立!
我们根据上面概念方法来画图....
让交叉点和交叉点点去匹配
那么图中连线的意思就是:1号有一条路可以去3号,二号也有一条路去3号,三号有一条路去4号,可以想象1号2号我们可以来一个伞兵任意选一个走到3号...(一个匹配),然后从3号走到4号,就先1/2---->3------>4两个匹配就走了三个点,剩下一个点就再来一个兵就可以啦。。。。那么
最小边覆盖=|P|-最大匹配这个公式就比较明了啦....

上马,马上来点解释:
// 0MS 244K
#include<stdio.h>
#include<string.h> #define MAX 121 int no_in,no_st;//交叉路的数量,街道数量
bool map[MAX][MAX];//map[i][j]表示i号交叉口有一条街道可以达到j号交叉口
int link[MAX];
bool useif[MAX]; bool dfs(int t)
{
for(int i=1;i<=no_in;i++)
{
if(!useif[i] && map[t][i])
{
useif[i]=true;
if(link[i]==-1 || dfs(link[i]))
{
link[i]=t;return true;
}
}
}
return false;
} int match()
{
int sum=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=no_in;i++)
{
memset(useif,false,sizeof(useif));
if(dfs(i))
sum++;
}
return sum;
} int main()
{
int T;
int a,b;
scanf("%d",&T);
while(T--)
{
memset(map,0,sizeof(map));
scanf("%d%d",&no_in,&no_st);
for(int i=1;i<=no_st;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;//注意是单项路
}
printf("%d\n",no_in-match());
}
return 0;
}

个人愚昧观点...欢迎指正、交流讨论

[置顶] 白话最小边覆盖总结--附加 hdu1151结题报告的更多相关文章

  1. [置顶] 白话二分匹配之最大匹配+附上hdu2063解题报告

    最近开始学习图论的二分匹配,关于最大匹配做一次小总结,希望自己后面回头来看一目明了,也对刚接触的人有帮助: ps:开始有的文字很多....对于很多人来说一看到文字就烦啦...不过这个总结是针对匈牙利算 ...

  2. win8.1系统下,点击一个窗口,【当前活动窗口】该窗口无法置顶

    两个或多个窗口同时显示在桌面的时候,点击下一层的窗口,无法置顶显示,无论怎么点击,还是隐藏在原置顶窗口的后面,只能手动把原置顶窗口最小化后,才能看到.例如,A窗口现在置顶,B窗口在A的后面,露出来一部 ...

  3. wpf 窗口最小化后,触发某事件弹出最小化窗口并置顶

    //如果窗口最小化了弹出并置顶----事件触发调用 ShowWindowAsync(new System.Windows.Interop.WindowInteropHelper(CommonHelpe ...

  4. Qt 窗口操作函数(置顶、全屏,最大化最小化按钮设置等)

    一.窗口置顶 与 取消置顶 void MainWindow::on_windowTopButton_clicked() { if (m_flags == NULL) { m_flags = windo ...

  5. HDU1151:Air Raid(最小边覆盖)

    Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  6. 将窗口置顶的方法:SetWindowPos、AttachThreadInput、SwitchToThisWindow

    将窗口置顶的方法:SetWindowPos.AttachThreadInput.SwitchToThisWindow [转]http://hi.baidu.com/neil_danky/item/f9 ...

  7. [Winform]检测exe是否已经运行,并将其置顶

    摘要 在很多pc应用中,基本上都需要有这样的判断,保证在一个终端只运行一个winform的client.并且如果最小化了,用户再次双击桌面图标的时候,将client置顶显示. 解决方案 需要使用win ...

  8. PKU 3020 Antenna Placement(拆点+最小边覆盖)(最大匹配)

    题目大意:原题链接 一个矩形中,有N个城市’*’,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市.问至少放置多少个基站才能使得所有的城市都覆盖无线? 提示:看清楚题目,' ...

  9. [置顶] Android开发笔记(成长轨迹)

    分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...

随机推荐

  1. C++中struct和class的区别 [转]

    一. C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构了,它已经获取了太多的功能. struct能包含成员函数吗?   能! struct能继承吗?  ...

  2. msxml 操作xml

    1.简介 在.NET平台,微软为C#或托管C++程序员提供了丰富的类库,用以支持各种需求,其中就有对XML文件操作的丰富的类.例如XMLDocument, XmlElement等.但是C++标准库中并 ...

  3. linux命令之partprobe

    使用fdisk工具只是将分区信息写入到磁盘,如果需要使用mkfs格式化并使用分区,则需要重新启动系统.partprobe 是一个可以修改kernel中分区表的工具,可以使kernel重新读取分区表而不 ...

  4. 武汉科技大学ACM :1009: 华科版C语言程序设计教程(第二版)习题6.11

    Problem Description n个人围成一圈,依次从1至n编号.从编号为1的人开始1至k报数,凡报数为k的人退出圈子,输出最后留下的一个人原来的编号. Input 首先输入一个t,表示有t组 ...

  5. java转换流

    转换流是把字节流转换成字符流,比如往一个文件中写内容,原本是一个字节一个字节的写,转换为字符流后,我们可以一个字符串,一个字符串的写,书写中文很方便 转换流class: OutputStreamWri ...

  6. js 浏览器版本检测

    整理了一下浏览器检测的js脚本 分享给大家 浏览器检测一般都是在网页打开的时候执行 使用js的闭包来实现页面加载以后执行的脚本 (function(){ //页面加载后执行的脚本 })() ; 检测浏 ...

  7. SSM框架搭建java.lang.ClassNotFoundException: org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

    在搭建 spring springMVC Mybatis 时候出错 将org.springframework.http.converter.json.MappingJacksonHttpMessage ...

  8. tcpdump使用和TCP/IP包分析

    关于tcpdump如何抓包,本文不再总结,可以查看 tcpdump的官方地址查看http://www.tcpdump.org 本文重点记录两个部分:           第一部分:tcpdump所抓包 ...

  9. phpEXCEL操作全解

    phpExcel中文帮助手册,列举了各种属性,以及常用的操作方法,难得是每一个都用实例加以说明,希望对大家有所帮助. phpExcel中文帮助手册,不可多得的好文章,供大家学习参考. 1.设置exce ...

  10. 如何使用sublime编辑器运行python程序

    现在越发喜欢sublime编辑器了,不仅界面友好美观.文艺,可扩展性还特别强. sublime本身是不具备运行python程序的能力的,需要做些设置才可以.以下是安装好sublime后设置的步骤: 点 ...