I Interesting Computer Game(取绑定点对中的一个,问最多能取多少不同的数,并查集判环)

题:https://ac.nowcoder.com/acm/contest/5673/I

题意:给定n对点对,每次只能从点对中取出之前没有取过的点,问最多能取到多少个不同的点。

分析:将点设为图上的点,点对即为边,离散化一下数据总共的点数为m,对于图的一个连通分量,假设它的大小为x,那么若这个连通分量有环则所有数都可以取到(贡献为x),若只是一个树形结构,则对答案的贡献为x-1。

   用并查集判一下有无环即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int M=2e5+5;
const int mod=998244353;
int f[M],a[M],b[M],vis[M],tmp[M];
int Find(int x){return x==f[x]?x:f[x]=Find(f[x]);}
int main(){
    int T;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        int n;
        scanf("%d",&n);

        for(int u,v,i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
            tmp[i]=a[i],tmp[i+n]=b[i];
        }
        sort(tmp+1,tmp+1+2*n);
        int m=unique(tmp+1,tmp+1+2*n)-tmp-1;
        for(int i=1;i<=m;i++)
            f[i]=i,vis[i]=0;

        for(int i=1;i<=n;i++){
            int x=lower_bound(tmp+1,tmp+1+m,a[i])-tmp;
            int y=lower_bound(tmp+1,tmp+1+m,b[i])-tmp;
            int u=Find(x),v=Find(y);
            if(u==v){
                vis[u]=1;
                continue;
            }
            f[u]=v;
            if(vis[u])vis[v]=1;
        }
        int ans=m;
        for(int i=1;i<=m;i++)
            if(f[i]==i&&!vis[i])
                ans--;
        printf("Case #%d: %d
",cas,ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/13432600.html