CF1209D Cow and Snacks(并查集)

Description

n n n 个零食, k k k 个客人,每个客人喜欢两个零食。一个客人会将剩下的零食中他喜欢的全部吃掉,如果一个也吃不到那么这位客人会不开心。你可以安排客人吃零食的顺序,求至少有多少客人不开心。

2 ≤ n ≤ 1 0 5 , 1 ≤ k ≤ 1 0 5 2 \leq n \leq 10^5, 1 \leq k \leq 10^5 2n105,1k105

Solution

因为一个客人可以吃两个零食,所以放弃二分图。考虑建立图论模型。零食是点,客人将它喜欢的两个零食连起来。

k k k 条边,每连一条边可以让联通分量的个数减少一个,所以答案与客人顺序无关。 k k k 个客人全高兴的情况下会减少 k k k 个联通分量,所以 k − k- k 实际的联通分量为重复连边的数量,也就是不高兴的客人数量。

可以用并查集实现。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;
inline int read() {
	int x = 0, f = 0; char ch = 0;
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
	return f ? -x : x;
}
int f[N];
int find(int k) {
	if (f[k] == k) return k;
	return f[k] = find(f[k]); 
} 
void merge(int a, int b) {
	a = find(a), b = find(b);
	if (a != b) f[b] = a;
}
int main() {
	int n = read(), k = read();
	for (int i = 1; i <= n; i++) f[i] = i;
	for (int i = 1; i <= k; i++) {
		int a = read(), b = read();
		merge(a, b);
	}
	int cnt = 0;
	for (int i = 1; i <= n; i++) if (f[i] == i) cnt++;
	printf("%d\n", k - (n - cnt));
	return 0;
}
posted @ 2020-02-20 11:04  ylxmf2005  阅读(43)  评论(0)    收藏  举报