题意:给定 n ( n < = 50 ) n(n <= 50) n(n<=50) 个数字和 1 个 k ( k < = 25 ) k(k <= 25) k(k<=25),挑出最多的数对 ( i , j ) (i,j) (i,j) 满足 a [ i ] = = a [ j ] ∗ k a[i] == a[j]*k a[i]==a[j]∗k。
题解:首先当 k = 1 k=1 k=1 的时候,很显然答案为 n / 2 n/2 n/2;当 k > 1 k > 1 k>1 时,如果 a [ i ] = = a [ j ] ∗ k a[i] == a[j]*k a[i]==a[j]∗k ,则建立一条 i i i 到 j j j 的有向边: i → j i \to j i→j,然后对整个图进行 01 间隔染色,染色为0的作为二分图左边的点,染色为1的点作为二分图右边的点,求一次二分图最大匹配。
题意: n ( n < = 60 ) n(n <= 60) n(n<=60) 个学生,每个人都说了自己所在的排名名次区间 [ X i , Y i ] [X_i,Y_i] [Xi,Yi],其中可能存在有人说谎,问最多有多少人说了实话。
题解:二分图最大匹配
首先,因为学生数小于等于 60, 所以如果排名区间差值大于60的,可以确保这个学生一定是可以说真话的,最后再来处理。对于区间小于等于 60 的,每个学生作为左边的点,右边的点就是区间 ( X i , X i + 1 , X i + 2 , . . . , Y i ) (X_i,X_{i+1},X_{i+2},...,Y_i) (Xi,Xi+1,Xi+2,...,Yi),两两连边,因为数字比较大,这里需要做一层离散化,先把所有区间按照值枚举出来,然后哈希到一个相对较小的下标中。然后,建立二分图求最大匹配。
题意: n ∗ n ( n < = 500 ) n*n (n <= 500) n∗n(n<=500) 的 01 矩阵上, 1的个数为 k ( k < = 1 0 5 ) k (k <= 10^5) k(k<=105),每次可以选择一整行消除整行的 1,或者一整列消除整列的 1,求选择最少的次数,将所有的 1 都消除。
题解:二分图最小顶点覆盖
将行作为二分图左边的点,列作为二分图右边的点,如果矩阵 A [ u ] [ v ] = 1 A[u][v] = 1 A[u][v]=1,则从左边的点 u u u 往右边的点 v v v 建立一条有向边 表示既可以通过选择行,也可以通过选择列来干掉这个 1。那么问题就变成了选择最少的顶点集合(行列集合),使得所有的边都被这些点集覆盖,转化成 二分图最小顶点覆盖 问题求解。
题意:有两个机器 A 和 B,机器 A 有 n n n 种工作模式,称为 m o d e [ 0 , . . . n − 1 ] mode[0,...n-1] mode[0,...n−1];机器 B 有 m m m 种工作模式,称为 m o d e [ 0 , . . . m − 1 ] mode[0,...m-1] mode[0,...m−1]。一开始他们都在 m o d e [ 0 ] mode[0] mode[0] 上工作,对于给定的 k k k 个作业,每一个作业都可以在这两台机器中的任意一台上以特定的模式进行处理。对于作业 i i i,约束可以表示为三元组 ( i , x , y ) (i, x, y) (i,x,y),这意味着它既可以在机器 A 的 m o d e [ x ] mode[x] mode[x] 处理,也可以在机器 B 的 m o d e [ y ] mode[y] mode[y] 处理。显然,为了完成所有的工作,我们需要不时地改变机器的工作模式,但不幸的是,机器的工作模式只能通过手动重启来改变。通过改变作业的顺序,并将每个作业分配给合适的机器,请编写一个程序,以减少重新启动机器的时间。
题解:二分图最小顶点覆盖
机器 A 作为左边的点, 机器 B 作为右边的点,对于所有的 ( x , y ) (x,y) (x,y),如果存在其中一个为 0,则不用管,直接完成;否则,建立一条 x → y x \to y x→y 的有向边,那么只要选择其中一个点,对应的边就被覆盖了,每条边代表一个任务,所有任务都需要完成;
题意:给定 n ∗ n ( n < = 100 ) n * n(n <= 100) n∗n(n<=100) 的格子,每个格子是 [ 1 , 50 ] [1,50] [1,50]的整数,问每次可以选择整行或者整列对数字进行消除,进行 k k k 次消除后,有哪些数字是一定不能被消除干净的。
题解:枚举 + 二分图最小顶点覆盖
枚举每个数字 r ( 1 < = r < = 50 ) r(1<=r<=50) r(1<=r<=50),然后枚举所有的格子,如果这个格子上的数字等于 r r r,那么对行到列建边,代表可以选择行,或者可以选择列对这个数字进行消除,问题转化成选择最少的行列,消除所有这些数字,即 二分图的最小顶点覆盖 问题。
题意:对一个 n ∗ m ( n , m < = 100 ) n*m(n,m <=100) n∗m(n,m<=100) 的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,并且限制了只有某些格子才可以放,而且在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。请问有多少个重要点。
题意:给定一个 n ∗ n n*n n∗n 的棋盘,黑白格子组成,白色格子可以放置棋子,黑色格子不能放置棋子,如果一行或者一列上有其它棋子,并且中间没有任何黑色格子,那么这样的放置是非法的,求尽量放置最多的棋子(类似国际象棋中的 “车”)。
题解:二分图最小顶点覆盖
首先将棋盘进行行分块,如下:
再进行列分块,如下:
那么我们发现,任何一个格子都属于 一个行分块 和 一个列分块,假设一格格子 ( r , c ) (r,c) (r,c),它的行分块编号为 x x x,列分块编号为 y y y,每个能够放置棋子的点一定是要么行分块要么列分块来决定的。那么,我们把每个能够放置棋子的点看成是二分图的边,即建立边 : x → y x \to y x→y,选择最少的点覆盖所有的边,就相当于把所有的格子上的位置都占据满了。
题意:在一个 n ∗ n ( n < = 100 ) n*n (n <= 100) n∗n(n<=100) 的矩阵中,找 n n n 个数 x ( 0 < = x < = 100 ) x(0<=x<=100) x(0<=x<=100) 使得这 n n n 个数都在不同的行和列里并且要求这 n n n 个数中的最大值和最小值的差值最小。
题解:二分枚举 + 二分图最小顶点覆盖
首先二分一个答案 r r r,然后枚举最小值 x x x,那么所有被选择的数字必须满足在 [ x , x + r ] [x, x+r] [x,x+r] 范围内,然后就转化成了选择最少的行列,使得这些数都能被选到了,即 二分图的最小顶点覆盖 问题。时间复杂度 O ( n 3 l o g n ) O(n^3logn) O(n3logn)。
题意:给定一棵 n ( n < = 1 0 5 ) n(n <= 10^5) n(n<=105) 个结点的树,以及 k ( k < = n ) k(k <= n) k(k<=n) 只猴子,每个结点上可以放置至多一只猴子,现在需要去掉一些树边,使得每只猴子至少和另一猴子有边相连,求剩下的最小树边。
题解:二分图最大匹配
首先,树一定是二分图。可以先对这棵树求一次二分匹配,得到匹配数 M,然后进行分情况讨论;
1) M ∗ 2 > = K M * 2 >= K M∗2>=K,那么很显然,可以选择这些匹配边两端放置这 K 只猴子,当 K 为偶数时,最小边数为 K / 2;K 为奇数时,最小边数为 ( K + 1 ) / 2 (K+1)/2 (K+1)/2;
2) M ∗ 2 < K M * 2 < K M∗2<K,其中 M ∗ 2 M * 2 M∗2 只猴子用去 M M M 条边,剩下 K − M ∗ 2 K-M*2 K−M∗2 只猴子每个占用一条边,最小边数为 M + K − M ∗ 2 = K − M M + K - M * 2 = K-M M+K−M∗2=K−M;
题意:给定一些投票,格式如下: ( C a t i , D o g j ) (Cat_i, Dog_j) (Cati,Dogj) 代表留下 i i i 号猫,放弃 j j j 号狗,或者 ( D o g i , C a t j ) (Dog_i, Cat_j) (Dogi,Catj) 留下 i i i 号狗,放弃 j j j 号猫。需要选出最大的一个投票集合,使得所有的选择都不冲突;
题解:最大独立集
对于三种投票 A、B、C,可以推导出:如果 A 和 B 冲突,B 和 C 冲突,那么 A 和 C 一定不冲突,所以这是一个二分图,那么对于冲突的两个投票建边,然后求最大独立集合即可。
题意:输入给定 n ( n < = 500 ) n(n <= 500) n(n<=500) 个订单,每个订单一个时间 t t t,以及 a 、 b 、 c 、 d a、b、c、d a、b、c、d 四个数,代表一辆出租车从 t t t 时刻开始,从 ( a , b ) (a,b) (a,b) 开到 ( c , d ) (c,d) (c,d),两点间花费的时间为两者曼哈顿距离,即: ∣ a − c ∣ + ∣ b − d ∣ |a-c| + |b-d| ∣a−c∣+∣b−d∣
每个订单时刻递增排序给出,如果第 i i i 个订单送完以后能够在前一分钟到达第 j j j 个订单的起点,那么认为可以由一辆出租车接单,问最少需要多少俩出租车才能完成这么多订单。
题解:对于两个订单 i i i 和 订单 j j j,判断时间和距离,如果满足就建立一条边,然后对这个图求最小路径覆盖。