Interesting Computer Game

牛客多校: https://ac.nowcoder.com/acm/contest/5673/I

题意:每次从两个数中选一个,也可以不选,但是选不能选之前重复的。
做法:同一行连一个边,然后一个图中有环的贡献就是这个图的大小;没环就是大小-1,用并查集维护就可以

#include <bits/stdc++.h>
#define inf 2333333333333333
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
//by war
//2020.8.3
using namespace std;
long long T,n,cnt,len,k,t,ans,tmp;
long long b[N],d[N],sum[N],vis[N];
 
struct node{
    long long l;
    long long r;
}a[N];
 
void in(long long &x){
    long long y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(long long x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}
 
long long find(long long x){
    if(d[x]==x) return x;
    return d[x]=find(d[x]);
}
 
signed main(){
    in(T);
    while(T--){
        in(n);
        ans=cnt=0;
        For(i,1,n){
            in(a[i].l);in(a[i].r);
            b[++cnt]=a[i].l;b[++cnt]=a[i].r;
        }
        sort(b+1,b+cnt+1);
        len=unique(b+1,b+cnt+1)-(b+1);
        For(i,1,n){
            a[i].l=lower_bound(b+1,b+len+1,a[i].l)-b;
            a[i].r=lower_bound(b+1,b+len+1,a[i].r)-b;
        }
        For(i,1,len) d[i]=i,sum[i]=1;
        For(i,1,n){
            k=find(a[i].l);t=find(a[i].r);
            if(k==t){
                vis[k]=1;
            }else{
                if(k>t){
                    vis[t]|=vis[k];
                    d[k]=t;
                    sum[t]+=sum[k];
                }else{
                    vis[k]|=vis[t];
                    d[t]=k;
                    sum[k]+=sum[t];
                }
            }
        }
        For(i,1,len){
            if(d[i]==i){
                ans+=sum[i];
                if(!vis[i]) ans--;
            }
            sum[i]=0;vis[i]=0;
        }
        cout<<"Case #"<<++tmp<<": "<<ans<<endl;
    }
    return 0;
}

 

posted @ 2020-08-03 22:15  WeiAR  阅读(114)  评论(0编辑  收藏  举报