最小生成树——洛谷并查集、口袋的天空

最小生成树——并查集

简单模板题-洛谷3367并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 N,MN,M ,表示共有 NN 个元素和 MM 个操作。

接下来 MM 行,每行包含三个整数 Z_i,X_i,Y_iZ**i,X**i,Y**i

当 Z_i=1Z**i=1 时,将 X_iX**i 与 Y_iY**i 所在的集合合并。

当 Z_i=2Z**i=2 时,输出 X_iX**i 与 Y_iY**i 是否在同一集合内,是的输出 Y ;否则输出 N

输出格式

对于每一个 Z_i=2Z**i=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N

输入输出样例

输入 #1复制

4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4

输出 #1复制

N
Y
N
Y

说明/提示

对于 30%30% 的数据,N \le 10N≤10,M \le 20M≤20。

对于 70%70% 的数据,N \le 100N≤100,M \le 10^3M≤103。

对于 100%100% 的数据,1\le N \le 10^41≤N≤104,1\le M \le 2\times 10^51≤M≤2×105,1 \le X_i, Y_i \le N1≤X**i,Y**iN,Z_i \in { 1, 2 }Z**i∈{1,2}。

#include <bits/stdc++.h>
using namespace std;
int n,m,z,x,y;
int father[10005];
int find(int point)
{
    if(father[point]==point)
        return point;
    return father[point]=find(father[point]);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        father[i]=i;
    for(int i=0;i<m;i++)
    {
        cin>>z>>x>>y;
        x=find(x);
        y=find(y);
        if(z==1)
        {
            if(x!=y)
                father[x]=y;
        }
        else {
            if(x==y)
                cout<<"Y\n";
            else
                cout<<"N\n";
        }
    }
    return 0;
}

进阶一点点的并查集的题,洛谷——口袋的天空

题目背景

小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。

有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。

题目描述

给你云朵的个数 NN,再给你 MM 个关系,表示哪些云朵可以连在一起。

现在小杉要把所有云朵连成 KK 个棉花糖,一个棉花糖最少要用掉一朵云,小杉想知道他怎么连,花费的代价最小。

输入格式

第一行有三个数 N,M,KN,M,K

接下来 MM 行每行三个数 X,Y,LX,Y,L,表示XX云和 YY 云可以通过 LL 的代价连在一起。

输出格式

对每组数据输出一行,仅有一个整数,表示最小的代价。

如果怎么连都连不出 KK 个棉花糖,请输出 No Answer

输入输出样例

输入 #1复制

3 1 2
1 2 1

输出 #1复制

1

说明/提示

对于 30%30% 的数据,N \le 100N≤100,M \le 10^3M≤103;

对于 100%100% 的数据,1 \le N \le 10^31≤N≤103,1 \le M \le 10^41≤M≤104,1 \le K \le 101≤K≤10,1 \le X,Y \le N1≤X,YN,0 \le L<10^40≤L<104。

#include <bits/stdc++.h>
using namespace std;
int n,m,k,l,x,y;
int father[10005];
int now=0,need=0;//记录合并了多少次,需要合并多少次
int all=0;//记录最小生成树各边之和
struct edge{
    int from,to,wage;
};
edge e[10005];
bool cmp(edge a,edge b)
{
    return a.wage<b.wage;
}
int find(int point)
{
    if(father[point]==point)
        return point;
    return father[point]=find(father[point]);
}
int main()
{
    cin>>n>>m>>k;
    need=n-k;
    for(int i=1;i<=n;i++)
        father[i]=i;
    for(int i=1;i<=m;i++)
    {
        cin>>e[i].from>>e[i].to>>e[i].wage ;
    }
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;++i)
    {
        x=find(e[i].from);
        y=find(e[i].to );
        if(x!=y)
            father[x]=y,++now,all+=e[i].wage ;
        if(now==need)
        {
            cout<<all;
            return 0;
        }
    }
    cout<<"No,Answer";
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值