COURSES
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 18454   Accepted: 7275

Description

Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is possible to form a committee of exactly P students that satisfies simultaneously the conditions:

  • every student in the committee represents a different course (a student can represent a course if he/she visits that course)
  • each course has a representative in the committee

Input

Your program should read sets of data from the std input. The first line of the input contains the number of the data sets. Each data set is presented in the following format:

P N
Count1 Student1 1 Student1 2 ... Student1 Count1
Count2 Student2 1 Student2 2 ... Student2 Count2
...
CountP StudentP 1 StudentP 2 ... StudentP CountP

The first line in each data set contains two positive integers separated by one blank: P (1 <= P <= 100) - the number of courses and N (1 <= N <= 300) - the number of students. The next P lines describe in sequence of the courses �from course 1 to course P, each line describing a course. The description of course i is a line that starts with an integer Count i (0 <= Count i <= N) representing the number of students visiting course i. Next, after a blank, you抣l find the Count i students, visiting the course, each two consecutive separated by one blank. Students are numbered with the positive integers from 1 to N.
There are no blank lines between consecutive sets of data. Input data are correct.

Output

The result of the program is on the standard output. For each input data set the program prints on a single line "YES" if it is possible to form a committee and "NO" otherwise. There should not be any leading blanks at the start of the line.

Sample Input

2
3 3
3 1 2 3
2 1 2
1 1
3 3
2 1 3
2 1 3
1 1

Sample Output

YES
NO

Source

题目解读:p门课,n个学生. 接下来p行,每行代表第i门课每行先输入这门课的学生数,然后在一次输入这些学生的编号。通过匈牙利算法问:能不能保证每门课至少都有一个学生. 算法要点:最大匹配数>=课程数p ?

匈牙利算法 代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> using namespace std; vector<int>g[310];
int link[310], vis[310];
int p, n; bool match(int x)
{
for(int i=0; i<g[x].size(); i++ )
{
if(!vis[g[x][i]] )
{
vis[g[x][i]] = true;
if(link[g[x][i]]==-1 || match(link[g[x][i]]) )
{
link[g[x][i]] = x;
return true;
}
}
}
return false;
} int hungary()
{
int tot=0;
memset(link, 255, sizeof(link));
for(int i=1; i<=n; i++)
{
memset(vis, 0, sizeof(vis));
if(match(i) )
{
tot++;
}
}
return tot;
}
int main()
{
int t;
int i, j, k; scanf("%d", &t);
while(t--)
{
scanf("%d %d", &p, &n);
int dd, u;
for(i=1; i<=n; i++)
g[i].clear();
for(i=1; i<=p; i++)
{
scanf("%d", &dd);
while(dd--)
{
scanf("%d", &u);
g[u].push_back(i);
}
}
int ans = hungary();
if(ans >= p)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}

Hopcroft-Karp 算法:

Hopcroft-Karp算法相比普通的匈牙利算法更快,所以当两边集合的点比较多时,为了快速完成匹配可以考虑这个算法,即使是有模板,但代码比较长且比较繁琐,容易写错。

敲的时候要特别注意!

H-K算法代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm> using namespace std;
int p, n;
vector<int>g[310];
int n1, n2;
int mx[310], my[310];
queue<int>que; int dx[310], dy[310];
bool vis[310]; bool find(int u)
{
for(int i=0; i<g[u].size(); i++)
{
if(!vis[g[u][i]] && dy[g[u][i]] == dx[u]+1 )
{
vis[g[u][i]] = true;
if(!my[g[u][i]] || find(my[g[u][i]]) )
{
mx[u] = g[u][i];
my[g[u][i]] = u;
return true;
}
}
}
return false;
} int matching()
{
memset(mx, 0, sizeof(mx));
memset(my, 0, sizeof(my));
int ans=0; while(true)
{
bool flag=false;
while(!que.empty())
que.pop();
memset(dx, 0, sizeof(dx));
memset(dy, 0, sizeof(dy));
for(int i=1; i<=n1; i++)
if(!mx[i] )
que.push(i);
while(!que.empty() )
{
int u=que.front();
que.pop();
for(int i=0; i<g[u].size(); i++ )
{
if(!dy[g[u][i]] )
{
dy[g[u][i]] = dx[u]+1;
if(my[g[u][i]])
{
dx[my[g[u][i]]] = dy[g[u][i]] + 1;
que.push(my[g[u][i]] );
}
else
flag=true;
}
}
}
if(!flag) break;
memset(vis, false, sizeof(vis));
for(int i=1; i<=n1; i++)
{
if(!mx[i] && find(i) )
ans++;
}
}
return ans;
} int main()
{
int t;
scanf("%d", &t);
int dd, u;
while(t--)
{
scanf("%d %d", &p, &n);
for(int i=1; i<=n; i++)
g[i].clear();
for(int i=1; i<=p; i++)
{
scanf("%d", &dd);
while(dd--)
{
scanf("%d", &u);
g[u].push_back(i);
}
}
n1=n; n2=p;
int ans = matching();
if(ans >= p )
printf("YES\n");
else
printf("NO\n"); }
return 0;
}

poj 1469 COURSES (二分图模板应用 【*模板】 )的更多相关文章

  1. POJ 1469 COURSES 二分图最大匹配 二分图

    http://poj.org/problem?id=1469 这道题我绝壁写过但是以前没有mark过二分图最大匹配的代码mark一下. 匈牙利 O(mn) #include<cstdio> ...

  2. POJ 1274 The Perfect Stall || POJ 1469 COURSES(zoj 1140)二分图匹配

    两题二分图匹配的题: 1.一个农民有n头牛和m个畜栏,对于每个畜栏,每头牛有不同喜好,有的想去,有的不想,对于给定的喜好表,你需要求出最大可以满足多少头牛的需求. 2.给你学生数和课程数,以及学生上的 ...

  3. poj 1469 COURSES(匈牙利算法模板)

    http://poj.org/problem?id=1469 COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:  ...

  4. Poj(1469),二分图最大匹配

    题目链接:http://poj.org/problem?id=1469 COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  5. POJ 1469 COURSES

    COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20478   Accepted: 8056 Descript ...

  6. poj 1469 COURSES 题解

    COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21515   Accepted: 8455 Descript ...

  7. poj 1469 COURSES 解题报告

    题目链接:http://poj.org/problem?id=1469 题目意思:有 N 个人,P个课程,每一个课程有一些学生参加(0个.1个或多个参加).问 能否使得 P 个课程 恰好与 P 个学生 ...

  8. poj——1469 COURSES

    COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24192   Accepted: 9426 Descript ...

  9. POJ 1469 COURSES(二部图匹配)

                                                                     COURSES Time Limit: 1000MS   Memory ...

随机推荐

  1. 使用assembly将maven项目pom.xml中的jar包打包

    参考官方网站:http://maven.apache.org/plugins/maven-assembly-plugin/usage.html 方法一:将pom.xml引入的jar包打到zip文件夹中 ...

  2. sprinvmvc整合swagger实现实时接口信息展示

    1.pom.xml引入swagger插件 <dependency> <groupId>io.springfox</groupId> <artifactId&g ...

  3. HTTP错误状态码定位与解决

    实践总结 本次基于对500错误定位为例,给大家讲解整个分析过程与解决方法. 1.本次实践为HTTP错误状态码定位提供一个高效.精确的定位方式,不仅仅局限于500错误. 2.针对500错误本身,可以基于 ...

  4. 版本号控制软件:TortoiseSVN高速上手

    百度百科对于SVN的一点解释: TortoiseSVN是Subversion版本号控制系统的一个免费开源client,能够超越时间的管理文件和文件夹.文件保存在中央版本号库,除了能记住文件和文件夹的每 ...

  5. rsync一些常用的命令

    渗透测试的时候会遇到RSYNC 匿名访问 在对一些大型互联网进行测试的时候经常会遇到rsync. 什么是Rsync Rsync(remote synchronize)是一个远程数据同步工具,可通过LA ...

  6. blind xxe攻击

    最近做啊里的题的时候遇到了 http://hivesec.net/web-security/%E5%85%B3%E4%BA%8Eblind-xxe.html

  7. ehcache缓存刷新问题

    ehcache可以设置时间来定时刷新缓存,但是这个只是清空值,key依旧保存着. 只有你第一次利用key获取值,key才会释放.

  8. 动态载入Layout 与 论Activity、 Window、View的关系

    1)动态载入Layout的代码是 getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null)); ...

  9. Axure教程:滑动进度条、圆形进度环的复杂交互效果实现方法

    滑动条.进度条.进度环,是产品原型中比较常见的进度展示功能.今天笔者分享的是使用Axure原型工具实现两种进度展示功能中相对复杂的交互效果. 效果一.可拖动.可显示进度值.可计算多个页面均值的滑动进度 ...

  10. 1.1 合用weightSum属性和layout_weight属性

    <打造高质量Android应用:Android开发必知的50个诀窍>第1章活用布局,本章将介绍Android布局相关的一些窍门和建议.通过本章,读者不仅可以学习如何从零开始创建特定类型的布 ...