CodeForces - 1209D 并查集

题意:

有 n个不同的糖果,从 1到 n编号。有 k个客人。要用糖果招待客人。对于每个客人,这些糖果中恰有两个是其最爱。第 i个客人最爱的糖果编号是 xi和 y。将 k

个客人任意排列,他们按顺序去拿自己最爱的糖果。
客人要拿到至少一个最爱的糖果才满意。
求不满意的客人的最小数目。

 

题解:

题目让求不满意客人最小数量,那么就肯定会有这样情况发生:

3 3

1 2

1 3

1 3

刚开始1号客人喜欢1和2糖果,因为1和2号糖果都没被用过,那么我们就先把1号糖果分给1号客人,后面第二个客人喜欢1和3号糖果,因为1号糖果用过了,所以3号糖果给2号客人。后面3号客人喜欢的糖果都被用过了,这个时候就要让1号客人放弃一号糖果去用2号糖果了。

 

我们也就是要解决放弃某个糖果去用另一个糖果这个抉择过程

 

这样的话我们可以用并查集,如果一个人喜欢1和2号糖果,那么就让1和2号糖果合并到一个集合里面。

这样的话合并1号糖果和2好糖果就相当于吃了1号或2号糖果中的一个,具体吃的哪个没有确定下来。这样的话就可以解决上面的问题

过程:

如果两个糖果在同一个集合中,说明两个糖果都被吃完了,如果两个糖果不在同一个集合中,说明至少还有一个糖果可以吃,那么把他们吃掉,同时两个集合合并为一个。

 

 

代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<math.h>
 6 #include<vector>
 7 #include<queue>
 8 #include<stack>
 9 #include<map>
10 using namespace std;
11 typedef long long ll;
12 const int maxn=1e5+10;
13 const int INF=0x3f3f3f3f;
14 const double eps=1e-10;
15 const int mod = 1e9+7;
16 #define mt(A,B) memset(A,B,sizeof(A))
17 #define lson l,m,rt*2
18 #define rson m+1,r,rt*2+1
19 #define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
20 int v[maxn];
21 void init(int n)
22 {
23     for(int i=0; i<=n; i++)
24         v[i]=i;
25 }
26 int finds(int x)
27 {
28     if(x==v[x]) return x;
29     return v[x]=finds(v[x]);
30 }
31 bool unite(int x,int y)
32 {
33     x=finds(x);
34     y=finds(y);
35     if(x!=y)
36     {
37         v[x]=y;
38         return true;
39     }
40     return false;
41 }
42 int main()
43 {
44     SIS;
45     int n,k,x,y,ans=0;
46     cin >> n >> k;
47     init(n);
48     for(int i=0; i<k; i++)
49     {
50         cin >> x >> y;
51         if(!unite(x,y)) ans++;
52     }
53     cout << ans << endl;
54     return 0;
55 }

 

posted @ 2020-04-26 11:11  kongbursi  阅读(144)  评论(0编辑  收藏  举报