D. Cow and Snacks(并查集+建图连通块)

https://codeforces.com/problemset/problem/1209/D

题意翻译

nn 种花,kk 个客人,每个人喜欢两种编号不同的花。但是每种花在花店里只有一束。

客人按顺序进入花店,会买走所有她喜欢且仍在店铺里的花。如果一个客人买不到任何一束花,那么她就会十分沮丧导致变成肥宅。现在你可以自己安排这 nn 个人的顺序,使得肥宅的数量最小。

翻译 by @皎月半洒花。

输入输出样例

输入 #1复制

5 4
1 2
4 3
1 4
3 4

输出 #1复制

1

输入 #2复制

6 5
2 3
2 1
3 4
6 5
4 5

说实话,我开始做的时候尝试最大流建图去做..发现弄不出来。

“Since every animal has exactly two favorite snacks, this hints that we should model the problem as a graph. ”(cf官方题解)

这个建边的思路还是很巧妙的。

因为思维上可以得出来,要让后面的人尽可能地只拿一个喜爱的东西(第一个人没办法肯定两个),要有一种顺序能构造出这样的情况。

那先把拿的东西连边,代表一个人喜爱的两个东西,连完边之后会发现变成很多个连通块。在一个连通块里,最优的方式是第一个人拿两个,每次后面的人拿1个。这样就构造出来了每个人只拿一个。

所以如果两个点不在一个连通块里,不用累加,因为两个都能取到。在两个点在一个连通块里,前面的已经把东西都用完了,那么这个人只能沮丧。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
LL fa[maxn];
LL find(LL x)
{
	if(x==fa[x]) return x;
	return fa[x]=find(fa[x]);
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n,m;cin>>n>>m;
  for(LL i=1;i<=n;i++) fa[i]=i;
  LL ans=0;
  while(m--)
  {
  	LL x,y;cin>>x>>y;
  	x=find(x);y=find(y);
  	if(x!=y){
  		fa[x]=y;	
	}
	else ans++;
  }
  cout<<ans<<endl;
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108633279