POJ1469_COURSES(二分圖最大匹配),二分圖最大匹配
解題報告
http://blog.csdn.net/juncoder/article/details/38136065
題目傳送門
題意:
n個學生p門課程,每個學生學習0或1以上的課程。
問:是否可以組成委員會,滿足
每個學生代表一門不同的課程
一門課程在委員會中有一名代表
思路:
很明顯的二分圖的完備匹配。
#include <map>#include <queue>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#define N 330#define P 110using namespace std;int mmap[N+P][N+P],n,p,pre[N+P],vis[N+P],m,k;int dfs(int x){ for(int i=p+1;i<=p+n;i++) { if(!vis[i]&&mmap[x][i]) { vis[i]=1; if(pre[i]==-1||dfs(pre[i])) { pre[i]=x; return 1; } } } return 0;}int main(){ int i,j,t; while(~scanf("%d",&t)) { while(t--) { memset(mmap,0,sizeof(mmap)); memset(pre,-1,sizeof(pre)); scanf("%d%d",&p,&n); for(i=1;i<=p;i++) { scanf("%d",&m); for(j=1;j<=m;j++) { scanf("%d",&k); mmap[i][k+p]=1; } } int ans=0; for(i=1;i<=p;i++) { memset(vis,0,sizeof(vis)); ans+=dfs(i); } if(ans==p) printf("YES\n"); else printf("NO\n"); } } return 0;}
COURSES
| Time Limit: 1000MS |
|
Memory Limit: 10000K |
| Total Submissions: 17166 |
|
Accepted: 6748 |
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
23 33 1 2 32 1 21 13 32 1 32 1 31 1
Sample Output
YESNO
Source
Southeastern Europe 2000
什是二分圖的匹配,最大匹配,帶權最大匹配
給定一個二分圖G,在G的一個子圖M中,M的邊集中的任意兩條邊都不依附於同一個頂點,則稱M是一個匹配。
選擇這樣的邊數最大的子集稱為圖的最大匹配問題(maximal matching problem)
如果一個匹配中,圖中的每個頂點都和圖中某條邊相關聯,則稱此匹配為完全符合,也稱作完備匹配。
求二分圖最大匹配可以用最大流或者匈牙利演算法。
參考資料:bk.baidu.com/view/501087.htm
二分圖最大匹配的Matlab程式
[num h] = maxnum(g);%g是二分圖鄰接矩陣%調用了一個自己寫maxnum函數,返回num就是最大值,h是hij(不唯一)以下是maxnum.m的內容,用的是匈牙利演算法其中還用了一個遞迴的incpath函數,尋找增廣路徑function [num h] = maxnum(g)s=size(g);global G_h;%矩陣hij記錄選中global G_g;%矩陣gij記錄匹配global G_v;%記錄當前一次路徑訪問過的節點G_h=false(s);%矩陣hij初始為空白G_g=g;%矩陣gij就是傳遞進來的參數gfor i=1:s(1) G_v=false(1,s(2));%每次初始化徑訪問過的節點為空白 incpath(i);%從Ai開始尋找增廣路徑endh=G_h;num=sum(h(:));%輸出最大匹配數,和匹配矩陣hclear global 'G_h';clear global 'G_g';endfunction OK = incpath(i)%從Ai開始global G_h;global G_g;global G_v;OK=false;j=find(~G_h(i,:)&G_g(i,:)&~G_v,1);%尋找合條件的Bjif isempty(j),return;end%找不到返回falseG_v(j)=true;%找到了,標記Bj為以訪問節點ii=find(G_h(:,j));%尋找Bj在原來匹配中if isempty(ii)%如果不在原匹配中G_h(i,j)=true;OK=true;return;end%找到增廣路徑末端,返回trueok=incpath(ii);%如果在原來的匹配中,根據匹配對應的Aii遞迴調用incpath尋找if ok %如果遞迴尋找返回成功G_h(i,j)=~G_h(i,j);G_h(ii,j)=~G_h(ii,j);OK=true;return;end%路徑反色返回trueend