您的位置:首页 > 其它

假期的宿舍

2016-08-21 14:22 106 查看
[b]假期的宿舍[/b]

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1433

[b]二分图匹配(最大流)[/b]

做到Candy(http://acm.split.hdu.edu.cn/showproblem.php?pid=4322)这道题,用A*写了半天TLE了,去网上搜题解,都是网络流的做法。问艾神用搜索做该怎么剪枝,艾神说他写的书上有讲很多剪枝策略,然而最快三天后书才能到....,所以就先试试网络流了。 之前没怎么接触过网络流,看了半天才看懂一些,于是就拿这题入门了。

这题是二分图匹配的入门题,将留校的同学和看望的同学作为一个点集,将本校生(床)作为另一个点集,并根据关系矩阵进行连接。(init的时候没把vector清了,简直智障...)

代码如下:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#define met(a,b) memset(a,b,sizeof(a));
#define N 55
using namespace std;
int match[2*N];
bool used[2*N];
int home
;
int bed
;
int mp

;
vector<int>e[2*N];
int T,n,sum,person;
void init(){
sum=0,person=0;
met(match,-1);
for(int i=0;i<2*N;++i)
e[i].clear();
}
bool dfs(int v){
used[v]=1;
for(vector<int>::size_type i=0;i<e[v].size();++i){
int u=e[v][i],w=match[u];
if(w<0||(!used[w]&&dfs(w))){//如果u没被匹配 或者 u已经被w匹配,但w可以找到其他匹配
match[v]=u;
match[u]=v;
return 1;
}
}
return 0;
}
int main(void){
scanf("%d",&T);
while(T--){
init();
/*----读取----*/
scanf("%d",&n);
for(int i=0;i<n;++i)//1有床 0没床
scanf("%d",&bed[i]);
for(int i=0;i<n;++i)//1回家 0不回家
scanf("%d",&home[i]);
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)//关系矩阵
scanf("%d",&mp[i][j]);
/*----建图----*/
for(int i=0;i<n;++i)
if(home[i]==0||bed[i]==0){//不回家或者没有床
person++;
for(int j=0;j<n;++j)
if(bed[j]==1&&(mp[i][j]==1||i==j)){//j有床并且i可以睡j的床
e[i].push_back(j+n);
e[j+n].push_back(i);
}
}
/*----最大匹配----*/
for(int i=0;i<2*n;++i)
if(match[i]<0){
met(used,0);
if(dfs(i))
sum++;
}
if(sum==person)printf("%c%c%c\n",94,95,94);
else printf("%c%c%c\n",84,95,84);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: