Codeforces Round #500 (Div. 2) [based on EJOI]--D - Chemical table

题目链接:http://codeforces.com/contest/1013/problem/D

题意:给你一个n*m的方格,然后再给你q个点(r,c),如果在这些方格中存在矩形的三个点,那么第四个点也可以得到,问你至少需要额外的多少个点,才能把表格填满。

思路:在做这题的时候一点思路都没有,唯一想到的就是暴力去做,但是会超时,想了挺久想不出来,就去看了看大佬的代码,发现竟然可以用并查集去做超级神奇,然后我自己试了几个样例都对,但我不会证明为什么会对,只能粗略地说一下:

当这一行或者这一列都不存在点的时候,你就必须在这一行或者这一列加一个点,然后分别隶属于两个根的点(两颗不同的树),需要额外的一个点把它们合并起来,最终所有的点都在一棵树中。

代码如下:

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<unordered_map>
#define INF 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
using namespace std;
#define MAXN 100010
int p[400005];
int find(int x)
{
    if(p[x]==x)return x;
    return p[x]=find(p[x]);
}
void join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
        p[fx]=fy;
}
int main()
{
    int n,m,q;
    scanf("%d%d%d",&n,&m,&q);
    for(int i=0;i<=n+m;i++)
        p[i]=i;
    while(q--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        join(x,y+n);
    }
    int ans=0;
    for(int i=1;i<=n+m;i++)
        if(find(i)==i)ans++;
    printf("%d\n",ans-1);//减去最终那棵树的根
    return 0;
}

还有一种dfs的做法,比较好理解一些

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<unordered_map>
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
using namespace std;
#define MAXN 100010
vector<int> c[400005];
int vis[400005];
void dfs(int x)
{
    if(vis[x]) return;
    vis[x]=1;
    for(int i=0; i<c[x].size(); i++) dfs(c[x][i]);
}
int main()
{
    int n,m,q;
    scanf("%d%d%d",&n,&m,&q);
    memset(vis,0,sizeof(vis));
    while(q--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        c[x].push_back(y+n);
        c[y+n].push_back(x);
    }
    int ans=0;
    for(int i=1;i<=n+m;i++) if(!vis[i]) dfs(i),ans++;
    printf("%d\n",ans-1);
}

猜你喜欢

转载自blog.csdn.net/dhydye/article/details/81319579