下面的程序利用匈牙利算法实现。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 52
int n, isStudent[N], goHome[N], relation[N][N], vis[N], match[N] = {0};
int head[N], cnt=0;
struct node{
int to;
int next;
node():next(-1){
}
}e[N*N];
void add_e(int from, int to){
e[cnt].to = to;
e[cnt].next = head[from];
head[from] = cnt++;
}
void get_i(int &x){
char ch = getchar();
x = 0;
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)){
x = x * 10 + ch - '0';
ch = getchar();
}
}
int hungary(int k){
int i, j;
for(i=head[k]; ~i; i = e[i].next){
j = e[i].to;
if(!vis[j]){
vis[j] = 1;
if(match[j] == 0 || hungary(match[j])){
match[j] = k;
return 1;
}
}
}
return 0;
}
int main(){
ios::sync_with_stdio(false);
int t, a, i, j, tot, sum;
get_i(t);
while(t--){
memset(head, -1, sizeof(head));
get_i(n);
for(i=1; i<=n; i++)
get_i(isStudent[i]);
for(i=1; i<=n; i++)
get_i(goHome[i]);
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
get_i(relation[i][j]);
// 构建二分图,add_e的第一个参数为学生,第二个参数为宿舍号
for(i=1; i<=n; i++){
if(isStudent[i] && !goHome[i]){
add_e(i, i);
}
}
for(i=1; i<=n; i++){
for(j=1; j<=n; j++){
if(relation[i][j]){
if((!isStudent[i] || !goHome[i]) && isStudent[j])
add_e(i, j);
}
}
}
tot = n; //在校总数,要去掉那些是学生但回家的情形
for(i=1; i<=n; i++){
if(isStudent[i] && goHome[i])
--tot;
}
memset(match, 0, sizeof(match));
sum = 0;
for(i=1; i<=n; i++){
memset(vis, 0, sizeof(vis));
if(!isStudent[i] || !goHome[i])
sum += hungary(i);
}
if(sum == tot)
cout<<"^_^"<