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;
}