zoukankan      html  css  js  c++  java
  • 【题解】Luogu P1195 口袋的天空

    口袋的天空

    题目背景

    小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空。
    有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖。
    

    题目描述

    给你云朵的个数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)(1≤X,Y≤N,0≤L<10000)
    
    30%的数据 N ≤ 100,M ≤ 1000
    

    输出格式

    对每组数据输出一行,仅有一个整数,表示最小的代价。
    
    如果怎么连都连不出K个棉花糖,请输出'No Answer'。
    

    输入、输出样例

    #1输入  
    3 1 2   
    1 2 1
    
    #1输出
    1
    

    题解

    首先说明本人用的算法(kruskal+并查集)
    根据kruskal算法我们可以确保我们能得到连通树的最小价值。
    那么只需要判断K了
    
    首先需要清楚:n个点连通需要最少n-1条边 
    分成k个组云 1组云(相当于n个点相连) 就需要n-1条边, 2组云 就可以用1组云去掉一条边得到 以此类推 k组云需要n-k条边
    那么对于无法连成的k就可以特判了
    后面在选边时,只需要选到cnt==k即可退出循环
    

    代码

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    struct Rec{ int x,y,w; };
    bool operator < (const Rec &a, const Rec &b){
    	return a.w < b.w;
    }
    // 重载运算符 与下面的cmp函数放在sort中作用一致
    const int N = 1e3 + 10,M = 1e4 + 10;
    int n,m,k,xx,yy,ww,cnt,sum,fa[N];
    Rec edge[M];
    
    int getfa1(int x){
    	if(fa[x] == x) return x;
    	return fa[x]=getfa1(fa[x]);
    }
    // 并查集 找到祖宗并且合并的操作 与下方getfa2函数作用一致
    int getfa2(int x){
    	int faa = x,t;
    	while(fa[faa] != faa) faa = fa[faa]; // 找到祖宗
    	while(fa[x] != x) t = fa[x], fa[x] = faa, x = t;//每个经历的点的爹都变成祖宗
    	return faa;
    }
    bool cmp(const Rec &a, const Rec &b){
    	return a.w < b.w;
    }
    //
    int main(){
    	//freopen("data1.in","r",stdin);
    	//freopen("data1.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);
    	if(n > m+k) {// 无解的特判
    		printf("No Answer
    ");
    		return 0;
    	}
    	cnt = n;
    	for(int i=1; i<=n; i++) fa[i] = i;
    	for(int i=0; i<m; i++) {
    		scanf("%d%d%d",&xx,&yy,&ww);
    		edge[i].x = xx, edge[i].y = yy, edge[i].w = ww;
    	}
    	sort(edge,edge+m);
    	for(int i=0; i<m; i++) {
    		if(cnt == k) break;// 达到k组棉花糖的要求
    		xx=getfa1(edge[i].x), yy=getfa1(edge[i].y), ww = edge[i].w;
    		if(xx == yy) continue;
    		sum+=ww, cnt--;// 取这个边
    		fa[xx]=yy;
    	}
    	printf("%d
    ",sum);
    	return 0;
    }
    

    (附Luogu AC图片)

  • 相关阅读:
    对vulnhub靶机lampiao的getshell到脏牛提权获取flag
    ssrf漏洞利用(内网探测、打redis)
    NC反弹shell的几种方法
    CTF长久练习平台
    Binder进程与线程ProcessState以及IPCThreadState
    Binder的Native实现libbinder
    Android 静态广播和动态广播接收顺序
    Android的Surface的创建
    android dialog,popupwindow,toast窗口的添加机制
    Android在WindowManagerService和ActivityManagerService中的Token
  • 原文地址:https://www.cnblogs.com/RemnantDreammm/p/13974209.html
Copyright © 2011-2022 走看看