[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. python之路——网络编程

    一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据, ...

  2. Leetcode with Python -> Sort

    349. Intersection of Two Arrays Given two arrays, write a function to compute their intersection. Ex ...

  3. Linux中awk后面的RS, ORS, FS, OFS 含义

    转载自http://blog.csdn.net/qq416647781/article/details/40649419   一.RS 与 ORS 差在哪   我们经常会说,awk是基于行列操作文本的 ...

  4. HTML5应用:setCustomValidity(message)接口

    本文转自http://tid.tenpay.com/?p=3592 HTML5表单验证给前端人员带来了便利,但是在用户体验上存在一些缺陷,默认的提示对用户很不友好,无法准确的获取想要的信息.好在大牛们 ...

  5. 获取任意网站的图标,标题栏logo,网站logo

    https://www.hao123.com/favicon.ico      网站换成你想要的  大多数都可以

  6. Nginx出现500错误解决办法

    查看错误日志D:\nginx\logs\error.log 得知:Nginx配置文件中会将路径中的 \t 默认转义成 空格 改为双斜杠就可以了

  7. Scala 基础(5)—— 构建函数式对象

    有了 Scala 基础(4)—— 类和对象 的前提,现在就可以来构建一个基于 Scala 的函数式对象. 下面开始构造一个有理数对象 Rational. 1. 主构造方法和辅助构造方法 对于每一个类的 ...

  8. [poj] 3690 Constellations || 矩阵hash

    原题 在大矩阵里找有几个小矩阵出现过,多组数据 将t个矩阵hash值放入multiset,再把大矩阵中每个hash值从multiset里扔出去,这样最后剩在multiset里的值就是没有找到的小矩阵, ...

  9. 输出读入优化——QAQ

    #include<bits/stdc++.h> const int RN=1e5; ],*ip=ib+RN,ob[RN+],*op=ob; inline int gc(){ ip==ib+ ...

  10. [ CodeVS冲杯之路 ] P1214

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/1214/ 这道题类似于最长区间覆盖,仅仅是将最长区间改成了最多线段,我们贪心即可 先将线段直接右边-1,然后按左边为第一 ...