[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=54859604

向大(hei)佬(e)势力学(di)习(tou)

二分图其实早就学了,可是无赖自己当初没好好听讲,变种就不说了,连匈牙利算法都不会。这次给了我一个好好复习改过自新的机会,既把匈牙利搞熟了,也算是理解了一些变种。

最小路径覆盖:

题意

用最少的出租车送完所有的乘客

将时间上可以接上的乘客连边

在一个图中,希望用最少的路径将所有点走遍,为什么 最小路径数=点总数-最大匹配 呢?

一张图,如果我们先暴力的各用一条路径把点覆盖

(拆点,连边表示可到达,虚线是假设的)



那么每多一个匹配,就可以少一个路径(车)。

代码

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std; const int oo=0x3f3f3f3f; int m,h[505],mm[505],tim[505],st[505][2],en[505][2];
int top,hh,head[1010];
struct Node{
int to,nxt;
}a[250010];
int vis[1010],girl[1010]; void adde(int fr,int to,int val){
hh++;
a[hh].to=to;
a[hh].nxt=head[fr];
}
int dis(int x){
return abs(st[x][0]-en[x][0])+abs(st[x][1]-en[x][1]);
}
int diss(int a,int b){
return abs(en[a][0]-st[b][0])+abs(en[a][1]-st[b][1]);
}
bool find(int x){//printf("/");
for(int i=head[x];i;i=a[i].nxt){//printf("he ");
int v=a[i].to;
if(!vis[v]){
vis[v]=1;
if(girl[v]==0||find(girl[v])){
girl[v]=x;
return true;
}
}
}
return false;
}
int hungary(){
int rt=0;
for(int i=1;i<=m;i++){
memset(vis,0,sizeof(vis));
if(find(i)) rt++;
}
return rt;
}
void solve(){
memset(a,0,sizeof(a));
memset(head,0,sizeof(head));
memset(girl,0,sizeof(girl));
scanf("%d",&m);
top=2*m+1;hh=1;
char str[10];
for(int i=1;i<=m;i++){
scanf("%s",str);
h[i]=(str[0]-'0')*10+(str[1]-'0');
mm[i]=(str[3]-'0')*10+(str[4]-'0');
tim[i]=h[i]*60+mm[i];//printf("tim[%d]=%d\n",i,tim[i]);
scanf("%d%d%d%d",&st[i][0],&st[i][1],&en[i][0],&en[i][1]);
}
for(int i=1;i<m;i++){
for(int j=i+1;j<=m;j++){
if(tim[i]+dis(i)+diss(i,j)<tim[j]){
adde(i,m+j,1);//printf("he ");
}
}
}
int ans=0;
ans=hungary();
printf("%d\n",m-ans);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}

最小点覆盖集:

最小点覆盖=最大匹配

为什么呢?假设还有一条边没有被覆盖,即它连的两个点都还没有被纳入匹配,那么这又是一个匹配了

题意

在n*n的方格中,放着一些东西。我有一个武器,每次可以清除一横排或一纵列,问最小使用次数

裸体一道,A的人太多了。然而对初学者来说,是开拓新思维。将行与列拆成两个点,两边即为一个点

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N=10000+5; int n,k,r[N],c[N];
int head[3*N],end[6*N],nxt[6*N],hh=0;
int vis[3*N],girl[3*N]; void adde(int a,int b){
hh++;
end[hh]=b;
nxt[hh]=head[a];
head[a]=hh;
}
bool find(int u){
for(int i=head[u];i;i=nxt[i]){
int v=end[i];
if(!vis[v]){
vis[v]=1;
if(girl[v]==0||find(girl[v])){
girl[v]=u;
return true;
}
}
}
return false;
}
int hungary(){
int rt=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(find(i)) rt++;
}
return rt;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++){
scanf("%d%d",&r[i],&c[i]);
adde(r[i],c[i]+n);//建边注意
}
printf("%d",hungary());
return 0;
}

总结:

1、此次算是学懂了一些了,二分图的变通就在于构图上,其中拆点的思想尤为重要,还需多练

二分图变种之最小路径覆盖、最小点覆盖集【poj3041】【poj2060】的更多相关文章

  1. Antenna Placement POJ - 3020 二分图匹配 匈牙利 拆点建图 最小路径覆盖

    题意:图没什么用  给出一个地图 地图上有 点 一次可以覆盖2个连续 的点( 左右 或者 上下表示连续)问最少几条边可以使得每个点都被覆盖 最小路径覆盖       最小路径覆盖=|G|-最大匹配数 ...

  2. HDU 1151 Air Raid(最小路径覆盖)

    题目大意: 有n个城市,m条道路,城市的道路是单向.  现在我们的伞兵要降落在城市里,然后我门的伞兵要搜索所有道路.问我们最少占领多少个城市就可以搜索所有的道路了. 我们可以沿着道路向前走到达另一个城 ...

  3. POJ 3020 Antenna Placement【二分匹配——最小路径覆盖】

    链接: http://poj.org/problem?id=3020 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  4. POJ-1422 Air Raid---二分图匹配&最小路径覆盖

    题目链接: https://vjudge.net/problem/POJ-1422 题目大意: 有n个点和m条有向边,现在要在点上放一些伞兵,然后伞兵沿着图走,直到不能走为止 每条边只能是一个伞兵走过 ...

  5. Taxi Cab Scheme POJ - 2060 二分图最小路径覆盖

    Running a taxi station is not all that simple. Apart from the obvious demand for a centralised coord ...

  6. P2764 最小路径覆盖问题 (最小点覆盖=顶点数-最大匹配)

    题意:最小路径覆盖 题解:对于一个有向图,最小点覆盖 = 顶点数 - 最大匹配 这里的最大匹配指的是将原图中每一个点拆成入点.出点, 每条边连接起点的出点和终点的入点 源点S连接每个点的出点,汇点T连 ...

  7. 【HDU3861 强连通分量缩点+二分图最小路径覆盖】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.有边u到v以及有 ...

  8. POJ 1422 二分图(最小路径覆盖)

    Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7278   Accepted: 4318 Descript ...

  9. hdu 1151 Air Raid(二分图最小路径覆盖)

    http://acm.hdu.edu.cn/showproblem.php?pid=1151 Air Raid Time Limit: 1000MS   Memory Limit: 10000K To ...

随机推荐

  1. 常用模块(shutil copy、压缩、解压)

    作用与功能 主要用于文件的copy,压缩,解压 导入shuitl模块: import shutil copy方法 1 1.shutil.copyfileobj()  打开file1,并copy写入fi ...

  2. Android之测试相关知识点

    程序员在开发的过程中一定要进行严格的测试: --->相关概念 * 根据是否知道源代码可以分为: 黑盒测试:只关心程序执行的过程和结果并不知道程序源代码. 白盒测试: 根据源代码写测试方法 或者 ...

  3. (总结)Linux下查看Nginx Apache MySQL的并发连接数和连接状态

    1.查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态:netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a ...

  4. 深入Spring Boot:ClassLoader的继承关系和影响

    前言 对spring boot本身启动原理的分析, Spring boot里的ClassLoader继承关系 可以运行下面提供的demo,分别在不同的场景下运行,可以知道不同场景下的Spring bo ...

  5. BZOJ4825 [Hnoi2017]单旋 【线段树】

    题目链接 BZOJ4825 题解 手模一下操作,会发现一些很优美的性质: 每次旋到根,只有其子树深度不变,剩余点深度\(+1\) 每次旋到根,[最小值为例]右儿子接到其父亲的左儿子,其余点形态不改变, ...

  6. Tomcat学习笔记(八)

    Tomcat载入器(二) Tomcat拥有不同的自定义类加载器,以实现对各种资源库的控制. 1.同一个web服务器里,各个web项目之间各自使用的java类库要互相隔离.  2.同一个web服务器里, ...

  7. HDU 5366 dp 递推

    The mook jong Accepts: 506 Submissions: 1281 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65 ...

  8. Python之面向对象:类的内置方法

    1.def __add__(self,other): c1+c2 两个实例的加法操作就是执行__add__()方法 2.__str__(self): print一个实例的时候,执行的是__str__( ...

  9. Reversion windows 2008 R2 STD to Datacenter

    1.To determine the installed edition, run: DISM /online /Get-CurrentEdition 2.To check the possible ...

  10. I2C总线介绍

    1. 简介 I2C, Inter-Integrated Circuit, 是一种串行通信总线,用于连接微控制器及其外围设备它是一种两线式串行总线(串行数据:SDA; 串行时钟频率:SCL), 利用电阻 ...