洛谷 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\n");//哭了 
86                 break;
87             }
88             else
89             {
90                 ++ans;//记录有床的学生数量 
91             }
92         }
93         if(ans == n - cnt)//如果留学校的人都有床 
94         {
95             printf("^_^\n");//笑了 
96         }
97     }
98     return 0;
99 }

猜你喜欢

转载自www.cnblogs.com/qqq1112/p/11332850.html