题解 P1682 【过家家】
glorious_dream · · 题解
题目大意:
有
算法讲解:
首先,可以发现有合并女生的操作,可以想到用并查集来维护。
考虑两个女生是朋友,把她们用并查集加在一起,形成一个联通块。在每一个联通块内,女生可以选择任何一个男生玩。这样假设一共形成
最后别忘了加上
总代码:
#include<bits/stdc++.h>
#define re register
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
inline void print(int x){
if(x/10) print(x/10);
putchar(x%10+'0');
}
const int M = 1e5+10;
int f[M],vis[500][500],cnt[M];
int n,m,k,t,ans=INT_MAX;
inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
struct dat{
int x,y;
}a[M];
signed main(){
n=read(),m=read(),k=read(),t=read();
for(re int i(1) ; i<=n ; ++i) f[i] = i;
for(re int i(1) ; i<=m ; ++i) a[i].x=read(),a[i].y=read();
for(re int i(1) ; i<=t ; ++i){
int x=read(),y=read();
int fx=find(x),fy=find(y);
if(fx == fy) continue;
f[fx] = fy;
}
for(re int i(1) ; i<=m ; ++i){
if(!vis[find(a[i].x)][a[i].y]){
cnt[find(a[i].x)]++;
vis[find(a[i].x)][a[i].y]=1;
}
}
for(re int i(1) ; i<=n ; ++i) if(cnt[i]) ans=min(ans,cnt[i]);
printf("%d",min(ans+k,n));
return 0;
}