口袋的天空洛谷并查集

题目背景

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

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

题目描述

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

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

输入输出格式

输入格式:

每组测试数据的

第一行有三个数N,M,K(1<=N<=1000,1<=M<=10000,1<=K<=10)

接下来M个数每行三个数X,Y,L,表示X云和Y云可以通过L的代价连在一起。(1<=X,Y<=N,0<=L<10000)

30%的数据N<=100,M<=1000

输出格式:

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

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

输入输出样例

输入样例#1:

3 1 2
1 2 1

输出样例#1:

1

说明

厦门一中YMS原创

又是一道水水的模板题,并查集,排序

//Gang
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define FOR(x,y,z) for(int x=y;x<=z;x++)
#define REP(x,y,z) for(int x=y;x>=z;x--)
#define ll long long
using namespace std;
int n,m,k;
int tot;
int fa[1000005];
int num=0;
struct node
{
    int x,y,l;
} e[100005];
int cmp(node a,node b)
{
    return a.l<b.l;
}
int find(int x)
{
//    int p,tmp;
//    p=x;
//    while(fa[x]!=x)
//    {
//        x=fa[x];//返回根节点;
//    }
//    while(x!=p)  //路径压缩
//    {
//        tmp = fa[p];
//        fa[p] = x;
//        p = tmp;
//    }
//    return x;//非递归
    return x==fa[x]?x:fa[x]=find(fa[x]);//递归,推荐非递归,递归会暴栈
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    FOR(i,1,m)
    scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].l);
    sort(e+1,e+m+1,cmp);
    FOR(i,1,n)fa[i]=i;
    FOR(i,1,m)
    {
        int fx=find(e[i].x),fy=find(e[i].y);
        if(fx!=fy)
        {
            num++;
            fa[fx]=fy;
            tot+=e[i].l;
        }
        if(num==n-k)
        {
            printf("%d\n",tot);
            return 0;
        }
    }
    printf("No Answer\n");

    return 0;
}
时间: 2024-12-26 06:22:57

口袋的天空洛谷并查集的相关文章

洛谷P2412 查单词 [trie树 RMQ]

题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词(每个单词内包含大小写字母).现在他想要找出某一段连续的单词内字典序最大的单词. 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示单词个数和询问个数. 接下来N行每行包含一个字符串,仅包含大小写字母,长度不超过15,表示一个单词. 再接下来M行每行包含两个整数x.y,表示求从第x到第y

洛谷 P2412 查单词

题目背景 滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西. 题目描述 udp2.T3如果遇到相同的字符串,输出后面的 蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词(每个单词内包含大小写字母).现在他想要找出某一段连续的单词内字典序最大的单词. 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示单词个数和询问个数. 接下来N行每行包含一个字符串,仅包含大小写字母,长度不超过15,表示一个单词. 再接下来M行每行包含两个整数x.y,表示求从第x到第y

洛谷P1195 口袋的天空 并查集

洛谷P1195 口袋的天空 并查集 将边从小到大排序,然后依次加边 看看是否能变成 K 个连通块,以及其最小话费 1 #include <cstdio> 2 #include <algorithm> 3 #define For(i,j,k) for(int i=j;i<=k;i++) 4 using namespace std ; 5 6 const int N = 1011,M = 10011,inf = 1e9 ; 7 struct edge{ 8 int x,y,val

洛谷P1547 Out of Hay 最小生成树 并查集

洛谷P1547 Out of Hay 最小生成树 并查集 路径压缩 #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <iomanip> using namespace std ;

洛谷P1551亲戚 并查集

洛谷P1551亲戚   并查集  按秩合并 + 路径压缩 #include <bits/stdc++.h> using namespace std ; const int N = 5011 ; int fa[N],rk[N] ; int n,m,Q ; inline void init() { for(int i=1;i<=n;i++) fa[ i ] = i,rk[ i ] = 1 ; } inline int find(int x) { if(x==fa[ x ]) return x

洛谷P1525 关押罪犯 并查集

无冲突 输出 0 洛谷P1525 关押罪犯 并查集 用拆点法 将一个点拆成两份 一个点和 x 的朋友相连 一个点和 x的敌人相连 若 x 与 y 是敌人 因为只有两个阵营 所以满足敌人的敌人就是朋友 然后 x 连向 y 的敌人 y 连向 x 的敌人 因为这是双向边 所以 y的朋友就是x的敌人就不用连了 如果某一时刻 getfather(e[ i ].from)==getfather(e[ i ].to) 这说明两个点已经是敌人关系的两个人 通过朋友关系连上了 那就结束了 1 #include <

洛谷1455 搭配购买(并查集)

洛谷1455 搭配购买 本题地址:http://www.luogu.org/problem/show?pid=1455 题目描述 明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有n朵云,云朵已经被老板编号为1,2,3,……,n,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉

洛谷 P3367 并查集模板

#include<cstdio> using namespace std; int n,m,p; int father[2000001]; int find(int x) { if(father[x]!=x) father[x]=find(father[x]); return father[x]; } void unionn(int i,int j) { father[j]=i; } int main() { scanf("%d%d",&n,&m); for

洛谷p3367 并查集模板

并查集是一种树型的数据结构,主要用来处理一些不相交集合的合并和更改问题. 比如找4的祖先,原来是 4->2->1,通过并查集路径压缩后,变为 4->1.也就变成了下图. 并查集的模板题: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m; int dad[2000001]; int find(int x)//很简单的find函数,网上还