1083 AlvinZH的青春记忆III

思路

难题,二分图。

说这是一个考察二分图的题目,你可以会说“不可能”,这哪里像一个二分图了!这真的是一个二分图,考察的是最小顶点覆盖。

你不知道最小顶点覆盖没有关系,别百度,先慢慢分析,别先入为主。

简化题意。A、B两列数字,若B[i]%A[j]==0,则二者需要去掉一个。问一共最少需要去掉多少人!

错误方法:二重循环记录可以整除的双方编号B[i]和A[j],记M1[A[j]]=M2[B[i]]=true,之后求M1、M2中为true的数量,取较小值输出。

为什么这是错的?我反手给出一个反例:2,4,6与2,10,12,计算出M1、M2中为true的数量都是3,但是答案却为2,因为只要去掉A中的2和B中的12即可。

错误的原因在于没有考虑可以两个数组中同时删去一些数据。那么对于两边都有可能删除数据的情况,该怎么处理呢?答案是不考虑。当然,我指的不是不考虑这种情况,而是不考虑点,转而考虑边,如果有B[i]%A[j]==0,则将来两个数之间连上一条边,表示需要删掉其中之一,我们的目标是删去其中一些点,使得两边不存在连线。

不存在连线是什么意思?没错,就是不存在增广路径!

增广路径的定义如下:若P是图G中一条联通两个未匹配顶点的路径,且属于M的边和不属于M的边在P上交替出现,则称P为相对于M的一条增广路径。

那么又如何处理删去点呢?总不能尝试删去一个点,DFS删点过程中再DFS找增广路径吧,想想都可怕。这里借用二分图匹配来完成模拟删点。先来个定义转化,二分图的一个匹配(包含若干条边的集合,且其中任意两条边没有公共端点):只要删掉这个匹配中每条边的其中一个点,就可以把这些边抹去。如果还有剩下的边,那么代表原图一定存在增广路径,如果求得了二分图最大匹配,代表不存在增广路径,假设最大匹配数为x,那么一定存在一种方法,删去最大匹配中的x个点,使二分图的这个最大匹配完全“崩溃”,即匹配边都不存在了。注意,删点的方法肯定不能任意地选匹配边两点中的一点,由于刚刚已经不存在增广路径,也就是说未匹配边中的点肯定有一个最大匹配顶点,删点的过程中不仅可以删去匹配边,也可以保证把未匹配边一同删去。

不知道你听明白了没有?说到底,这是一个二分图匹配的最小顶点覆盖。我竟然从实际的角度说明最小顶点覆盖=二分图最大匹配数,需要说明:理论上也已经证明。

最小顶点覆盖:最少的顶点数使得二分图G中的每条边都至少与其中一个点相关联。二分图的最小顶点覆盖数=二分图的最大匹配数。

很明显,我们找的就是这个最小顶点数,由于每条边都与其中一个点关联,如果把这个最小顶点数所对应顶点全部删去,那么所有的边也没了。

接下来就是求二分图最大匹配了,不说了,参考AlvinZH的学霸养成记IV

分析

最小点覆盖练习题

二营长,你他娘的意大利炮呢

关于最小顶点覆盖=二分图的最大匹配参考

二分图详解

参考代码

//
// Created by AlvinZH on 2017/12/5.
// Copyright (c) AlvinZH. All rights reserved.
// #include <cstdio>
#include <cstring>
#include <vector>
#define MaxSize 1005
#define INF 0x3f3f3f3f
using namespace std; int n, m, ans;
vector<int> G[MaxSize];//记录匹配的双方弟子
int match[MaxSize];//记录匹配点
int visit[MaxSize];//记录是否访问 int A[MaxSize], B[MaxSize]; bool dfs(int x)//寻找增广路径
{
for (int i = 0; i < G[x].size(); ++i)
{
int to = G[x][i];
if(!visit[to])
{
visit[to] = 1;
if(!match[to] || dfs(match[to]))
{
match[to] = x;
return true;
}
}
}
return false;
} int MaxMatch()
{
ans = 0;
memset(match, 0, sizeof(match));
for (int i = 1; i <= m; ++i)
{
memset(visit, 0, sizeof(visit));//清空访问
if(dfs(i)) ans++;//从节点i尝试扩展
}
return ans;
} int main()
{
while(~scanf("%d %d", &n, &m))
{
for (int i = 1; i < MaxSize; ++i)
G[i].clear();
for (int i = 1; i <= n; ++i)
scanf("%d", &A[i]);
for (int i = 1; i <= m; ++i)
{
scanf("%d", &B[i]);
for(int j = 1; j <= n; ++j)
{
if(B[i] % A[j] == 0)
G[i].push_back(j);
}
} printf("%d\n", MaxMatch());
}
}

2016级算法期末模拟练习赛-E.AlvinZH的青春记忆III的更多相关文章

  1. 2016级算法期末模拟练习赛-F.AlvinZH的青春记忆IV

    1086 AlvinZH的青春记忆IV 思路 难题,动态规划. 这是一道很有意思的题,因为它不仅卡了时间,也卡了空间,而且卡的很妙很迷. 光是理解题意已经有点难度,简化题意:两串数字序列,相等的数字定 ...

  2. 2016级算法期末模拟练习赛-B.AlvinZH的青春记忆I

    1083 AlvinZH的青春记忆I 思路 中等题,动态规划. 简化题意,一个环上取数,数不可相邻,取取得数之和最大值. 环不好表示,可以解开变成一列数,那么答案应为下列两种情况较大者. ①:取第一个 ...

  3. 2016级算法期末模拟练习赛-C.AlvinZH的青春记忆II

    1084 AlvinZH的青春记忆II 思路 中等题,二分. 简化题意,一列数字,每秒会自动-1,特殊操作可以使一个数在1s内-k,问这些数都减至0需要多久. 答案肯定在[1,xMax]之间,采用二分 ...

  4. 2016级算法期末模拟练习赛-D.AlvinZH的序列问题

    1111 AlvinZH的序列问题 思路 中等题,动态规划. 简化题意,. 坑点一:二维int数组MLE,明显会超过内存限制,由于\(n\)最大为1e4,那么我们的dp数组最大也是1e4,考虑使用sh ...

  5. 2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行

    1063 wuli51和京导的毕业旅行 思路 中等题,二分+贪心. 简化题意,将m+1个数字分成n份,ans为这n段中每段数字和的最大值,求ans最小值及其方案. 对于这种求最小的最大值,最常用的方法 ...

  6. 2016级算法期末上机-H.难题·AlvinZH's Fight with DDLs III

    1119 AlvinZH's Fight with DDLs III 思路 难题,最小点覆盖. 分析题意,某一个任务,既可以在笔记本A的 \(a\) 模式下完成,也可以在笔记本B的 \(b\) 模式下 ...

  7. 2016级算法期末上机-D.简单·AlvinZH's Fight with DDLs I

    1117 AlvinZH's Fight with DDLs I 思路 简单题,动态规划. 本题与期末练习赛B题很相似,而且更为简单些.简化问题:在数字序列上取数,不能取相邻的数. DP数组定义,dp ...

  8. 2016级算法期末上机-F.中等·AlvinZH's Fight with DDLs II

    1118 AlvinZH's Fight with DDLs II 思路 中等题,贪心. 理解题意,每次攻击中,可以使某个敌人生命值-1,自己生命值减去∑存活敌人总攻击力. 贪心思想,血量少攻击高的要 ...

  9. 2016级算法第二次上机-E.AlvinZH的儿时梦想——运动员篇

    862-AlvinZH的儿时梦想--运动员篇 思路 难题. 应该想到,不管给出的数据如何,每一个淘汰的人不会对最终答案产生任何影响,所以每次淘汰就把人除掉就可以了,最后剩下的两个人计算它们从开始到相遇 ...

随机推荐

  1. 静态方法调静态属性用self,$this不可以

  2. 有些标签的class有多个值,用空格隔开的,是什么意思阿?

    这个div同时应用了三个class.三个class的设置都会对它起作用,相互冲突时,越后面的class优先权越高.

  3. java可视化

    1.java关闭窗口代码. ft.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); IE打开  Weiler-Atherton任意多边形裁剪 http:/ ...

  4. JAVA array,map 转 json 字符串

    public class User { private String username; private String password; public String getUsername() { ...

  5. Mac下eclipse 启动时出现An error has occurred. See the log file的问题

    eclipse原来可以使用的好好的,装了多个版本的jdk后,打开eclipse出现An error has occurred. See the log file的问题,经过查找,可能原因之一是机子装了 ...

  6. .net 分布式架构之分布式锁实现(转)

    分布式锁是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防 ...

  7. Dockerfile RUN, CMD & ENTRYPOINT

    Dockerfile RUN, CMD & ENTRYPOINT 在使用Dockerfile创建image时, 有几条指令比较容易混淆, RUN, CMD, ENTRYPOINT. RUN是在 ...

  8. CodeForces 518B Tanya and Postcard (题意,水题)

    题意:给定两个字符串,然后从第二个中找和第一个相同的,如果大小写相同,那么就是YAY,如果大小写不同,那就是WHOOPS.YAY要尽量多,其次WHOOPS也要尽量多. 析:这个题并不难,难在读题懂题意 ...

  9. (转)SQL Server内存遭遇操作系统进程压榨案例

    原文地址:http://www.cnblogs.com/zc_0101/p/3592259.html 场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没 ...

  10. EBS常用接口表

    AP接口表: AP_INVOICES_INTERFACE AP_INVOICE_LINES_INTERFACE 涉及的请求: 应付款管理系统开放接口导入 涉及案例: 运费导AP.费用导AP PO接口表 ...