【Nowcoder】2020牛客暑期多校训练营(第八场)I - Interesting Computer Game | 并查集、思维、离散化

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

题目大意:

从1~n给出n组数据,每次可以选择a 或者选择b,选了之后不能在选,问最多选多少个?

题目思路:

和之前总结的一道题很像:https://blog.csdn.net/qq_43857314/article/details/107253264

注意到关联性,所以不可以贪心的去搞

考虑并查集

当一些点连同时

如果当前存在n-1条边,也就是是一棵树,你总可以使得有n-1个点被选

如果大于n-1条边,只需要再选一个点即可

因为可以不选,所以就结束了~

注意到数据范围,所以离散化一下即可

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include <string.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pp;
const ll INF=1e17;
const int Maxn=1e6+10;
const int maxn =1e6+10;
const int mod= 998244353;
const int Mod = 1e6+7;
const int S = 1000;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
int pre[maxn];
struct node{
    int x,y;
}q[maxn];
ll sz[maxn],ed[maxn];
int vis[maxn];
vector<int>v;
int Find(int x){
    return pre[x] == x?x:pre[x] = Find(pre[x]);
}
int getid(ll x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int main()
{
    int cas = 0;
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        v.clear();
        for(int i=1;i<=n;i++){
            scanf("%d%d",&q[i].x,&q[i].y);
            v.push_back(q[i].x);
            v.push_back(q[i].y);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        int szt = v.size();
       /// debug(szt);
        printf("Case #%d: ",++cas);
        for(int i=1;i<=szt;i++) pre[i] = i,sz[i] = 1,ed[i] = 0,vis[i] = 0;
 
 
        for(int i=1;i<=n;i++){
            int x = getid(q[i].x),y = getid(q[i].y);
            int dx = Find(x),dy = Find(y);
            if(dx != dy){
                pre[dx] = dy;
                sz[dy] += sz[dx];
                ed[dy] += ed[dx]+1;
            }
            else ed[dx]++;
        }
        ll ans = 0;
        for(int i=1;i<=szt;i++){
            int di = Find(i);
            if(!vis[di]){
                vis[di] = 1;
                if(ed[di]>=sz[di]) ans+=sz[di];
                else ans+=sz[di]-1;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/107768887