问题 E: 魔法交流活动

题目描述

魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。
N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。
魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。
由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。
现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。

输入

两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5) 
接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX) 
保证输入数据合法。

输出

输出一个正整数R,表示符合条件的魔法阵的魔力值之和。

样例输入

4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6

样例输出

12
-

大致题意分析:

  有n个点,选取n-1条边把他们全部连起来形成一棵树,每条边都有一个权值;要求1:所有的边的权值的最大值最小,然后还又要求2:这棵树中的所有的边权值的和最大。

  思路:这个题目是对边来进行筛选的,需要用克鲁斯卡尔蒜法。这个蒜法是对边来进行操作的,按照边来逐渐形成整棵最小生成树。

具体需要跑两边,第一遍从小到大对边进行一次筛选,筛选出的边的集合可以构成一颗树即可;这是最后一条新加进来的边就是最大的权值maxmin(要求1达成)。

    第二遍,从大到小,具体从等于最小的最大边权值maxlen的边开始跑一遍,直到筛选出的边的集合可以构成一颗树即可,进行筛选、求和,即为最终结果。


ac代码:

 #include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include<math.h>
#include <string.h>
#include<set>
using namespace std;
#define inf 0x7fffffff
#define maxn 10000000
const double pi=acos(-1.0);
#define ll long long
#define N 100008 int n,m;
struct Edge//存边的结构体
{
int a,b;//两个顶点的编号
ll dis;
Edge(int a=,int b=,ll dis=):a(a),b(b),dis(dis) {}
} edge[N*]; int root[N]; int findroot(int a) //返回点a的根节点,并查集
{
if(root[a]==a)
return a;
return root[a]=findroot(root[a]);
}
int unite(int a,int b) //将a和b节点用并查集的思路连接到一起
{
if(a==b)return ;//在联通块内部加上的边,及a-b出现在同一个集合内部了
else
{
root[a]=b;
return ;
}
}
bool cmp(Edge x,Edge y)
{
return x.dis<y.dis;
}
int fact1(int n) //kruscal蒜法调用1次,计算出最小的最大值maxlen
{
for(int i=; i<=n; i++)
root[i]=i; int cnt=;
ll ans=(ll)inf*(-);
int i=;
while(cnt<n-)//从小到大
{
if(unite(findroot(edge[i].a),findroot(edge[i].b))== )
{
cnt++;
ans=max(ans,edge[i].dis);
}
i++;
}
return ans;
}
ll fact2(int n,int maxlen) //kruscal蒜法调用2次,求出在manlen范围下的最小生成树的边集的和
{
for(int i=; i<=n; i++)
root[i]=i;
int cnt=;
ll ans=;
int i=m;
while(cnt<n-)//从大到小跑边
{
if(edge[i].dis<=(ll)maxlen && unite(findroot(edge[i].a),findroot(edge[i].b))== )
{
cnt++;//统计不形成回路的边数,等于n-1时跳出循环
ans+=edge[i].dis;
}
i--;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{ int x,y;
ll v;
for(int i=; i<=m; i++)
{
scanf("%d%d%lld",&x,&y,&v);
edge[i]=Edge(x,y,v);//不习惯这种方式可以手动逐一赋值! }
sort(edge+,edge++m,cmp);//按边权值升序排列 int maxlen=fact1(n);//找到合法的最大长度 printf("%lld\n",fact2(n,maxlen));//求出最终结果
} return ;
}

【克鲁斯卡尔蒜法-最小生成树算法】-zzuli-2271 -Problem -E-魔法交流活动的更多相关文章

  1. c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树

    c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路 ...

  2. 最小生成树之克鲁斯卡尔(Kruskal)算法

    学习最小生成树算法之前我们先来了解下 下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的 ...

  3. 克鲁斯卡尔(Kruskal)算法

    概览 相比于普里姆算法(Prim算法),克鲁斯卡尔算法直接以边为目标去构建最小生成树.从按权值由小到大排好序的边集合{E}中逐个寻找权值最小的边来构建最小生成树,只要构建时,不会形成环路即可保证当边集 ...

  4. JS实现最小生成树之克鲁斯卡尔(Kruskal)算法

    克鲁斯卡尔算法打印最小生成树: 构造出所有边的集合 edges,从小到大,依次选出筛选边打印,遇到闭环(形成回路)时跳过. JS代码: //定义邻接矩阵 let Arr2 = [ [0, 10, 65 ...

  5. 数据结构与算法——克鲁斯卡尔(Kruskal)算法

    目录 应用场景-公交站问题 克鲁斯卡尔算法介绍 克鲁斯卡尔算法图解 克鲁斯卡尔算法分析 如何判断回路? 代码实现 无向图构建 克鲁斯卡尔算法实现 获取一个点的终点解释 应用场景-公交站问题 某城市新增 ...

  6. 克鲁斯卡尔(Kruskal)算法(代码)

    算法代码 C#代码 using System; using System.Linq; namespace Kruskal { class Program { static void Main(stri ...

  7. 最小生成树之Kruskal(克鲁斯卡尔)算法

    学习最小生成树算法之前我们先来了解下下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所 ...

  8. 经典问题----最小生成树(kruskal克鲁斯卡尔贪心算法)

    题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...

  9. [数据结构]最小生成树算法Prim和Kruskal算法

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

随机推荐

  1. 超详细的Tensorflow模型的保存和加载(理论与实战详解)

    1.Tensorflow的模型到底是什么样的? Tensorflow模型主要包含网络的设计(图)和训练好的各参数的值等.所以,Tensorflow模型有两个主要的文件: a) Meta graph: ...

  2. 【bcrypt】vue项目中bcrypt安装报错

    [报错] 报错时安装方法: npm install bcrypt [解决方法] npm install bcryptjs 用 bcryptjs 替换 bcrypt 即可.

  3. PHP LUHN算法验证银行卡

    <?php /* 16-19 位卡号校验位采用 Luhn 校验方法计算: 第一步:把信用卡号倒序(61789372994) 第二步:取出倒序后的奇数位置上的号码, 相加等到总和s1.(eg:s1 ...

  4. Javascript 闭包何时回收?

    定义 闭包是函数和声明该函数的词法环境的组合.闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量. 范例 fun ...

  5. java多线程中篇(一) —— Thread详情

    简介 简言之,现在的JDK线程模型基于操作系统原生线程,所以模型依赖于操作系统对线程的支持,另外Windows和Linux系统提供的线程模型就是一对一的 所以可以简单认为: 现在Java线程与操作系统 ...

  6. Mkdown常用语法

    这篇笔记停了两天,今天开始整理, 写这篇笔记主要是加强下自己的mkdown语法知识, 也当作练手之作. Mkdown 语法简介 标题 [h1 - h6] # ~ ###### 一般# 作为标题, 只有 ...

  7. ORAchk - 数据库配置检查工具

    1.概要2.下载和安装3.如何执行4.执行过程5.报告6.参考 1.概要 ORAchk之前被称为RACcheck,后来它的检查范围进行了扩展,改名为了ORAchk,它是在数据库系统进行健康检查的一个专 ...

  8. 字典的学习2——参考Python编程从入门到实践

    遍历字典 1. 遍历所有键值对 eg1: user_0 = { 'username': 'efermi', 'first': 'enrico', 'last': 'fermi',}for key, v ...

  9. 从零开始学Flask框架-007

    Flash消息 from flask import flash 渲染Flash消息,在基模板base.html中引入get_flashed_messages() {% extends "bo ...

  10. AVR单片机教程——如何使用本教程

    这是一篇元教程(meta-tutorial)——其他教程教你怎么使用AVR单片机,本篇教程教你如何使用本系列教程. 我们的教程已经把板载LED讲完了,但是教会你的不应该只是如何使用LED.你应该已经知 ...