假期的宿舍

假期的宿舍

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

二分图匹配(最大流)

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

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

代码如下:

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<iostream>
 5 #define met(a,b) memset(a,b,sizeof(a));
 6 #define N 55
 7 using namespace std;
 8 int match[2*N];
 9 bool used[2*N];
10 int home[N];
11 int bed[N];
12 int mp[N][N];
13 vector<int>e[2*N];
14 int T,n,sum,person;
15 void init(){
16     sum=0,person=0;
17     met(match,-1);
18     for(int i=0;i<2*N;++i)
19         e[i].clear();
20 }
21 bool dfs(int v){
22     used[v]=1;
23     for(vector<int>::size_type i=0;i<e[v].size();++i){
24         int u=e[v][i],w=match[u];
25         if(w<0||(!used[w]&&dfs(w))){//如果u没被匹配 或者 u已经被w匹配,但w可以找到其他匹配
26             match[v]=u;
27             match[u]=v;
28             return 1;
29         }
30     }
31     return 0;
32 }
33 int main(void){
34     scanf("%d",&T);
35     while(T--){
36         init();
37         /*----读取----*/
38         scanf("%d",&n);
39         for(int i=0;i<n;++i)//1有床 0没床
40             scanf("%d",&bed[i]);
41         for(int i=0;i<n;++i)//1回家 0不回家
42             scanf("%d",&home[i]);
43         for(int i=0;i<n;++i)
44         for(int j=0;j<n;++j)//关系矩阵
45             scanf("%d",&mp[i][j]);
46         /*----建图----*/
47         for(int i=0;i<n;++i)
48         if(home[i]==0||bed[i]==0){//不回家或者没有床
49             person++;
50             for(int j=0;j<n;++j)
51             if(bed[j]==1&&(mp[i][j]==1||i==j)){//j有床并且i可以睡j的床
52                 e[i].push_back(j+n);
53                 e[j+n].push_back(i);
54             }
55         }
56         /*----最大匹配----*/
57         for(int i=0;i<2*n;++i)
58         if(match[i]<0){
59             met(used,0);
60             if(dfs(i))
61                 sum++;
62         }
63         if(sum==person)printf("%c%c%c\n",94,95,94);
64         else printf("%c%c%c\n",84,95,84);
65     }
66 }

 

转载于:https://www.cnblogs.com/barrier/p/5792681.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值