HDU-1856-(并查集 每个快最大数 模板)

题目

王先生选择了一个足够大的房间来容纳这些男孩。那个没有被选中的男孩必须立即离开房间。房间里有10000万男孩,从一开始的1到10000万。在王的选择之后,任何两个还在这个房间里的人都应该是朋友(直接的或间接的),否则就只剩下一个男孩了。考虑到所有直接的朋友对,你应该决定最好的方式。

输入

输入的第一行包含一个整数n (0≤n≤100 000)——直接friend-pairs的数量。下面的n行每一行都包含一对数字a和B,用一个空格隔开,这表明a和B是直接的朋友。(≤1≠B A、B≤10000000)

输出

一行中的输出恰好包含一个整数,该整数等于王先生可能保留的最大男孩数。

模板,可以合并的时候用cnt数组维护。
也可以统计答案的时候直接看是哪个组的 这个组++。

#include <cstdio>
#include <cstring>
#define m(a,b) memset(a,b,sizeof a)
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=100005;
const int INF=0x3f3f3f3f;
int f[N],cnt[N];
int vis[N];
int seek(int x)
{
    int ances=x;
    while(ances!=f[ances])
        ances=f[ances];
    int father=x;
    while(x!=ances)
    {
        father=f[x];
        f[x]=ances;
        x=father;
    }
    return ances;
}
int main()
{
    int m;
    while(~scanf("%d",&m))
    {
        if(!m)
        {
            printf("1\n");
            continue;
        }
        m(vis,0),m(cnt,0);
        for(int i=1;i<=N;i++)
            f[i]=i;
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            vis[a]=1,vis[b]=1;
            int ra=seek(a),rb=seek(b);
            if(ra!=rb)
                f[ra]=rb;
        }
        int maxn=0;
        for(int i=1;i<=N;++i)
        {
            if(!vis[i])
                continue;
            f[i]=seek(i);
            ++cnt[f[i]];
            maxn=maxn>cnt[f[i]]?maxn:cnt[f[i]];  //也可以放在最后把每个祖先的值找最大的
        }
        printf("%d\n",maxn);
    }
}
#include <cstdio>
#include <cstring>
#define m(a,b) memset(a,b,sizeof a)
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=100005;
const int INF=0x3f3f3f3f;
int f[N],cnt[N];
int vis[N];
int seek(int x)
{
    int ances=x;
    while(ances!=f[ances])
        ances=f[ances];
    int father=x;
    while(x!=ances)
    {
        father=f[x];
        f[x]=ances;
        x=father;
    }
    return ances;
}
int main()
{
    int m;
    while(~scanf("%d",&m))
    {
        if(!m)
        {
            printf("1\n");
            continue;
        }
        m(vis,0),m(cnt,0);
        for(int i=1;i<=N;i++)
            f[i]=i,cnt[i]=1;
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            vis[a]=1,vis[b]=1;
            int ra=seek(a),rb=seek(b);
            if(ra!=rb)
            {
                f[ra]=rb;
                cnt[rb]+=cnt[ra];
            }
        }
        int maxn=0;
        for(int i=1;i<=N;++i)
        {
            if(!vis[i])    //vis标记的并不是祖先 而是出先过的数。
                continue;
            maxn=maxn>cnt[i]?maxn:cnt[i];
        }
        printf("%d\n",maxn);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值