- 题库 :洛谷
- 题号 :2055
- 题目 :假期的宿舍
- link :https://www.luogu.org/problem/P2055
首先明确一下:校内的每个学生都有一张床(只是校内的有)
思路 :分析题目发现是求所有在校学生能否全部有床睡(注意:只需在校学生有床睡,及不回家的;这个床可以是自己的,也可以是朋友的);于是,这道题我们可以把它想象成一个二分图,如样例图:
a -> b表示a可以睡b的床(注意:虽然样例中没有2 -> 2的边,但你仔细读题就会发现题目中的原话---)
由于题目里给的是一个邻接矩阵,我们便可以无视蓝点所连出去的边,只用红点去搜就行了(代码里写了也不要紧)
代码 :
1 #include <bits/stdc++.h> 2 #define INF 0x3f3f3f3f 3 using namespace std; 4 int T, n, head[201], num, vis[201], choose[201], q[201], w[201], ans, cnt; 5 struct node 6 { 7 int next, to; 8 }stu[40001]; 9 inline void add(int x, int y)//链式前向星 10 { 11 stu[++num].next = head[x]; 12 stu[num].to = y; 13 head[x] = num; 14 return; 15 } 16 inline int dfs(int u)//二分图匈牙利算法模板 17 { 18 for(register int i = head[u]; i; i = stu[i].next) 19 { 20 int k = stu[i].to; 21 if(vis[k]) 22 { 23 continue; 24 } 25 vis[k] = 1; 26 if(!choose[k] || dfs(choose[k])) 27 { 28 choose[k] = u; 29 return 1; 30 } 31 } 32 return 0; 33 } 34 signed main() 35 { 36 scanf("%d", &T); 37 while(T--)//多组数据 38 { 39 memset(choose, 0, sizeof(choose));//初始化 40 memset(head, 0, sizeof(head)); 41 num = 0; 42 ans = 0; 43 cnt = 0; 44 scanf("%d", &n); 45 for(register int i = 1; i <= n; ++i) 46 { 47 scanf("%d", &q[i]); 48 } 49 for(register int i = 1; i <= n; ++i) 50 { 51 scanf("%d", &w[i]); 52 if(q[i] && !w[i])//如果他是本校学生&&他不回家 53 { 54 add(i, i);//自己可以睡自己的床 55 } 56 } 57 for(register int i = 1; i <= n; ++i) 58 { 59 for(register int j = 1, x; j <= n; ++j) 60 { 61 scanf("%d", &x); 62 if(x) 63 { 64 if(q[i])//如果i是本校学生(及有一张床) 65 { 66 add(j, i);//j也可以睡 67 } 68 if(q[j])//同理 69 { 70 add(i, j); 71 } 72 } 73 } 74 } 75 for(register int i = 1; i <= n; ++i) 76 { 77 if(q[i] && w[i])//如果是本校学生&&不留在学校(如果是外校的就不可能回家啊) 78 { 79 ++cnt;//记录一下有多少个,以后算答案方便 80 continue;//不用管他有没有床 81 } 82 memset(vis, 0, sizeof(vis)); 83 if(!dfs(i))//如果有一个学生没有床 84 { 85 printf("T_T ");//哭了 86 break; 87 } 88 else 89 { 90 ++ans;//记录有床的学生数量 91 } 92 } 93 if(ans == n - cnt)//如果留学校的人都有床 94 { 95 printf("^_^ ");//笑了 96 } 97 } 98 return 0; 99 }