题解 P1682 【过家家】
这题其实并不难,也可以不用到网络流相关知识(当然,网络流是一种更通用的方法)。
考虑到点之间存在这两种关系
- 男生和女生之间,可以在一起
- 女生和女生之间,是朋友
我们对这两种关系分别建图。
易得,由于题目朋友关系的传递性,我们可以用Floyd或并查集预处理好这些“小团体”。
对于一个小团体内部,可以共享男生。易得如果女生这边只存在这个小团体,游戏进行的次数等于这个小团体共同能够连接的男生个数。
我们处理出所有小团体单独能进行的游戏次数,全局取min即可。
注意到我们还没有考虑k,易得k直接与前面的答案累加再与n取min即可,因为只要这个数小于n,给一次强行连接的机会,一定能把游戏延长一回合。
还是放一下代码。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 255;
int n,m,k,f;
bool g[maxn][maxn];
bool g2[maxn][maxn];
int x,y;
bool vis[maxn];
bool que[maxn];
int numa,numb;
int kokona = 0x3f3f3f3f;
int get_ans(int numa,int numb){
return numa;
}
void floyed(){
for (int k=1;k<=n;k++){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if(g2[i][k] & g2[k][j])g2[i][j] = true;
}
}
}
}
int main(){
cin>>n>>m>>k>>f;
for (int i=1;i<=m;i++){
cin>>x>>y;
g[x][y] = true;
}
for (int i=1;i<=f;i++){
cin>>x>>y;
g2[x][y] = true;
g2[y][x] = true;
}
for (int i=1;i<=n;i++)g2[i][i]=true;
floyed();
for (int i=1;i<=n;i++){
if(vis[i])continue;
for (int i=1;i<=n;i++)que[i]=false;
numa=numb=0;
for (int j=1;j<=n;j++){
if(g2[i][j]){
vis[j] = true;
numb++;
for (int k=1;k<=n;k++){
if(g[j][k]){
if(!que[k]){
que[k] = true;
numa++;
}
}
}
}
}
kokona = min(kokona,get_ans(numa,numb));
}
cout<<min(kokona+k,n)<<endl;
return 0;
}