HNU 11979 Roll call 二分图匹配

题意:

  众所周知,老师经常在班级上点名。点名是从名单上叫一个人的名字或者id来判断名单上这个人是否在场。学生们总是有各种各样的理由不来,所以他们需要其他人帮他们答到。但是打到工作不是这么简单,出于各种考虑,他们答道遵循以下原则。

1. 每个来上课的人必须给自己达到;

2. 每个来上课的人,只能帮另外一个人达到;

3. 如果一个人想帮助另外一个人答道,那么他们id的差至少大于等于K。

  现在老师又要点名了,请问是否存在一种情况,使老师相信每个人都到场了。

输入:

  第一行有一个整数T,表示接下来会有T组数据。

  对于每组数据,第一行包含三个整数N, M, K
(1<=N<=10^9,2<=M,K<=150),告诉你一共有N个学生,有M个学生到场了,K是id的最小差。第二行有M个整数,表示到场学生的id。

思路:
二分图匹配

代码: 用的增广路算法,还没学MK

 1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4
5 using namespace std;
6
7 const int MAXN = 400;
8
9 bool vis[MAXN];
10 bool present[MAXN];
11 int id[MAXN];
12 int matched[MAXN];
13 int N, M, K;
14
15 inline int myAbs(int x) {
16 return x>0 ? x : -x;
17 }
18
19 bool dfs(int v) {
20 vis[v] = true;
21 for (int u = 1; u <= N; u++) if ((present[u]^present[v]) && (myAbs(u-v)>=K)) {
22 int w = matched[u];
23 if (w<0 || (!vis[w] && dfs(w))) {
24 matched[v] = u;
25 matched[u] = v;
26 return true;
27 }
28 }
29 return false;
30 }
31
32 int Match() {
33 int res = 0;
34 memset(matched, -1, sizeof(matched));
35 for (int v = 1; v <= N; v++) {
36 if (matched[v]<0) {
37 memset(vis, false, sizeof(vis));
38 if (dfs(v)) {
39 res++;
40 }
41 }
42 }
43 return res;
44 }
45
46 int main() {
47 #ifdef Phantom01
48 freopen("HNU11979.txt", "r", stdin);
49 #endif // Phantom01
50
51 int T;
52 scanf("%d", &T);
53
54 while (T--) {
55 scanf("%d%d%d", &N, &M, &K);
56 for (int i = 0; i < M; i++) {
57 scanf("%d", &id[i]);
58 }
59 if (N>(M<<1)) {
60 puts("N");
61 continue;
62 }
63 memset(present, false, sizeof(present));
64 for (int i = 0; i < M; i++)
65 present[id[i]] = true;
66 if ((N-M)==Match()) puts("Y");
67 else puts("N");
68 }
69
70 return 0;
71 }

HNU11979

HNU 11979 Roll call 二分图匹配,码迷,mamicode.com

时间: 2024-10-13 08:10:01

HNU 11979 Roll call 二分图匹配的相关文章

hdu 3829 Cat VS Dog 二分图匹配 最大点独立集

Cat VS Dog Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Problem Description The zoo have N cats and M dogs, today there are P children visiting the zoo, each child has a like-animal and a dislike-animal, if the

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

BZOJ 1854 游戏(二分图匹配或并查集)

此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个题需要常数优化,不能每次都fillchar一遍used数组.可以用队列将使用的used点加入,然后需要初始化的时候弹出即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <i

HDU 3081:Marriage Match II(二分图匹配+并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也可以和男生A过家家(具有传递性).给出m个关系,代表女生a和男生b没有争吵过.给出k个关系,代表女生a与女生b是好朋友.每一轮过家家之后,女生只能选择可以选择并且没选过的男生过家家,问游戏能进行几轮. 思路:因为n<=100,因此支持O(n^3)的算法,挺容易想到是一个二分图匹配的.(出现在我的网络

11082 - Matrix Decompressing (网络流建模|二分图匹配)

该题是一道经典的二分图匹配的题目 .现在终于有点明白什么是二分图匹配了,其实说白了就是依赖于最大流算法之上的一种解决特定问题的算法 . 所谓二分图,就是我们假定有两个集合A和B,每个集合中有若干元素(点),其中源点与A相连,汇点与B相连,并且他们的总容量决定了最终答案的上限,所以一定要维护好 . 然后由A中的点向B中的点连线,他们之间也有一定的容量制约关系(具体看题目中的边权值限制).这样就可以求出最大流量匹配了. 有时我们要求完美匹配,即所有流入的量等于流出的量  . 该题构思极其巧妙,因为我

BZOJ 1191: [HNOI2006]超级英雄Hero(二分图匹配)

云神说他二分图匹配从来都是用网络流水过去的...我要发扬他的精神.. 这道题明显是二分图匹配.网络流的话可以二分答案+最大流.虽然跑得很慢.... ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea

二分图匹配(指派问题)

指派问题: 有N台计算机和K个任务,我们可以给每台计算机分配一个任务,每台计算机能够处理的任务种类不同,请求出最多能够处理的任务的个数. 思路:二分图匹配,可以这样来定义无向二分图,G=(UuV,E); U 代表计算机的顶点集合,V代表任务的顶点集合,对于任意u属于U和v属于V,计算机u能够处理的任务v<=>(u,v)属于E 二分图例子: 对原图做如下改变: 将原图中所有无向边e改为有向边,方向从U到V,容量1,增加源点s和汇点t,从s向所有的顶点u属于U连一条容量为1的边,从所有的顶点V属于

算法模板——二分图匹配

实现功能为二分图匹配 本程序以Codevs2776为例 详见Codevs2776 1 type 2 point=^node; 3 node=record 4 g:longint; 5 next:point; 6 end; 7 var 8 i,j,k,l,m,n:longint; 9 c,f:array[0..1000] of longint; 10 a:array[0..1000] of point; 11 procedure add(x,y:longint);inline; 12 var p: