[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. 一个初学者的辛酸路程-基于Django写BBS项目

    前言 基于Django的学习 详情 登录界面 找个模板 http://v3.bootcss.com/examples/signin/ 右键,检查源码     函数 def login(request) ...

  2. sqlalchemy 查询姿势总结

    sqlalchemy查询使用 1.带条件查询 查询是最常用的,对于各种查询我们必须要十分清楚,首先是带条件的查询 #带条件查询 rows = session.query(User).filter_by ...

  3. 孤荷凌寒自学python第五十二天初次尝试使用python读取Firebase数据库中记录

    孤荷凌寒自学python第五十二天初次尝试使用python读取Firebase数据库中记录 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数 ...

  4. 孤荷凌寒自学python那些事第二天

    孤荷凌寒自学python第二天 Python的变量声明 (完整学习过程屏幕记录视频在文末,手写笔记在文末) Python的变量声明不必要显式指定变量类型 甚至也不需要进行显式的声明 比javascri ...

  5. 500 OOPS: vsftpd: refusing to run with writable anonymous root

    500 OOPS: vsftpd: refusing to run with writable anonymous root 以下就是解决的三个步骤,其中第一步,是我一直没有搞明白的,也是其中的重点: ...

  6. iis如何处理并发请求

    文章:IIS是怎么处理同时到来的多个请求的? 文章:你真的了解:IIS连接数.IIS并发连接数.IIS最大并发工作线程数.应用程序池的队列长度.应用程序池的... 文章:IIS最大工作进程数设置引发串 ...

  7. 设置EntityFramework中decimal类型数据精度问题(EF默认将只会保留到2为精度)

    原文:设置EntityFramework中decimal类型数据精度 EF中默认的decimal数据精度为两位数,当我们数据库设置的精度大于2时,EF将只会保留到2为精度. e.g. .19990将会 ...

  8. 【bzoj3669】[Noi2014]魔法森林 Kruskal+LCT

    原文地址:http://www.cnblogs.com/GXZlegend/p/6797748.html 题目描述 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看 ...

  9. [SQL Server]关于标识列,标识从1开始计数的的方法

    DBCC CHECKIDENT ('表名',  RESEED, 0) //从30开始 DBCC  CHECKIDENT  (jobs,  RESEED,  30)

  10. zjoi2018day1 游记

    3.18 这一天乘车来到衢州,这已经是第四次了,来衢州二中考过两次普及,一次提高,都不是特别好. 到了以后先去了宾馆,是在帝京,和NOIP一样的酒店,连房间都是隔壁,然后一进去就连上了隔壁的WIFI ...