CF1012B

题目链接

题目描述

给你一幅\(N \ast M\)的图,图中有一些点已经被选定.
你有两个选择:
1.花费1代价选择一个没有被选过的点.
2.花费0代价选择一个点\(\left(r_{2},c_{2} \right)\),当且仅当点\(\left(r_{1},c_{2} \right), \left(r_{2},c_{1} \right), \left(r_{1},c_{1} \right)\)被选择.
问选择所有点的最小代价.
图

输入输出格式

输入格式:

第一行包含三个整数n,m,q,表示图的大小和已有的点的数量.
以下q行包含两个整数ri,ci,每个都描述了已经拥有的点,且保证输入中的所有点都不同.
\(\left(1 \leq n,m \leq 200000 \right)\)
\(\left(0 \leq q \leq \min \left( n\ast m,200000\right)\right)\)
\(\left( 1 \leq r_{i} \leq n , 1 \leq c_{i} \leq m \right)\)

输出格式:

一个整数表示最小代价.

样例

输入样例 输出样例
2 2 3 1 2 2 2 2 1 0

思路

1.并查集

将原图抽象为N+M个点
对于一个存在的点(x,y),将bcj[x]与\(bcj \left[ y + N \right]\)合并
考虑选择一个点\(\left(r_{2},c_{2} \right)\)
\(\left(r_{1},c_{2} \right), \left(r_{2},c_{1} \right), \left(r_{1},c_{1} \right)\)已被选择时
思考并查集的连接情况
........................................
(\(r_{1} , r_{2} , c_{1} , c_{2}\)的连通性)
........................................
会发现$ r_{2} , c_{2} $已经在一个联通块中
对于一个联通块来说,其内部的点都是可以互相构成的
整个图联通,其实就对应了原图所有点都被选择
那么先将0费的点按上述过程连接起来,就构成了0费时的联通块
而将两个联通块合一的代价是显而易见的
就是选择一个点的代价

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#define ll long long
#define ull unsigned long long
#define ci const int&
#define cl const long long&
#define cul const undigned long long&
#define io_f std::ios::sync_with_stdio(false)
using namespace std;

int n,m,q;
int bcj[400100];

int fd(ci x) {return x==bcj[x]?x:bcj[x]=fd(bcj[x]);}

int main() {
    io_f;
    int a,b;
    cin>>n>>m>>q;
    for(int i=1;i<=n+m;i++) bcj[i]=i;
    for(int i=1;i<=q;i++) {
        cin>>a>>b;
        bcj[fd(bcj[a])]=fd(bcj[b+n]);
    }
    int ans=0;
    for(int i=1;i<=n+m;i++)
        if(bcj[i]==i)ans++;
    cout<<ans-1<<endl;

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ullio/p/9397520.html