2019河北省大学生程序设计竞赛(重现赛)J-舔狗 (拓扑排序)

题目链接:https://ac.nowcoder.com/acm/contest/903/J


题意:给你 n 个舔狗和他喜欢的人,让你俩俩配对(只能和喜欢它的和它喜欢的),求剩下的单身狗数量。

思路:类似于拓扑排序,由入度最少的边开始配对,也就是被最少的舔狗喜欢的(甚至是没有)。将已经配对的舔狗进行标记,更新入度后重新加入优先队列,最后用总数减去标记数就是答案了。

总结:一开始我的思路是对的呐,但是我太菜了,卡在没办法处理同时配对2个点和维护他们入度,看完别人的处理才发现自己是局限于找入度为0而不是找入度最少。

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue>
 4 #include<cstring>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn = 1e6 + 5;
 8 const int INF = 0x3f3f3f3f;
 9 int n;
10 int in[maxn];
11 int vis[maxn];
12 int like[maxn];
13 struct node{
14     int u,v;//u是编号,v是入度。
15     bool friend operator<(node a,node b)//优先队列使入度小的排在前面
16     {
17         return a.v > b.v;
18     }
19 };
20 void solve()
21 {
22     int ans = 0;
23     priority_queue<node> q;
24     for(int i = 1;i<= n;i++)
25     {
26         q.push( node{i,in[i]} );//将所有点加入队列;
27     }
28     while(!q.empty())
29     {
30         node w = q.top(); q.pop();
31         if(vis[w.u] || vis[ like[w.u] ]) continue; //如果他或者他喜欢的配对了就不能配了;
32         ans += 2;
33         vis[w.u] = 1;
34         vis[ like[w.u] ] = 1;
35         //更新入度,反正优先队列,多跑几次没关系
36         q.push( node{like[like[w.u]],--in[ like[like[w.u]] ] } );//like[like[w.u]] 是指舔狗喜欢的人喜欢的人。
37     }
38     printf("%d\n",n-ans);
39 }
40 int main()
41 {
42     scanf("%d",&n);
43     for(int i = 1;i <= n;i++)
44     {
45         scanf("%d",&like[i]);
46         in[like[i] ]++;
47     }
48     solve();
49     return 0;
50 }

猜你喜欢

转载自www.cnblogs.com/Carered/p/10924316.html