【克鲁斯卡尔蒜法-最小生成树算法】-zzuli-2271 -Problem -E-魔法交流活动
问题 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-魔法交流活动的更多相关文章
- c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树
c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路 ...
- 最小生成树之克鲁斯卡尔(Kruskal)算法
学习最小生成树算法之前我们先来了解下 下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的 ...
- 克鲁斯卡尔(Kruskal)算法
概览 相比于普里姆算法(Prim算法),克鲁斯卡尔算法直接以边为目标去构建最小生成树.从按权值由小到大排好序的边集合{E}中逐个寻找权值最小的边来构建最小生成树,只要构建时,不会形成环路即可保证当边集 ...
- JS实现最小生成树之克鲁斯卡尔(Kruskal)算法
克鲁斯卡尔算法打印最小生成树: 构造出所有边的集合 edges,从小到大,依次选出筛选边打印,遇到闭环(形成回路)时跳过. JS代码: //定义邻接矩阵 let Arr2 = [ [0, 10, 65 ...
- 数据结构与算法——克鲁斯卡尔(Kruskal)算法
目录 应用场景-公交站问题 克鲁斯卡尔算法介绍 克鲁斯卡尔算法图解 克鲁斯卡尔算法分析 如何判断回路? 代码实现 无向图构建 克鲁斯卡尔算法实现 获取一个点的终点解释 应用场景-公交站问题 某城市新增 ...
- 克鲁斯卡尔(Kruskal)算法(代码)
算法代码 C#代码 using System; using System.Linq; namespace Kruskal { class Program { static void Main(stri ...
- 最小生成树之Kruskal(克鲁斯卡尔)算法
学习最小生成树算法之前我们先来了解下下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所 ...
- 经典问题----最小生成树(kruskal克鲁斯卡尔贪心算法)
题目简述:假如有一个无向连通图,有n个顶点,有许多(带有权值即长度)边,让你用在其中选n-1条边把这n个顶点连起来,不漏掉任何一个点,然后这n-1条边的权值总和最小,就是最小生成树了,注意,不可绕成圈 ...
- [数据结构]最小生成树算法Prim和Kruskal算法
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总 ...
随机推荐
- EscaperWrapper 转义和反转义
System.out.println("转义HTML,注意汉字:"+StringEscapeUtils.escapeHtml4("<font>chen磊 x ...
- mysql 严格模式 Strict Mode
mysql 严格模式 Strict Mode 找到MySQL安装目录下的my.cnf(windows系统则是my.ini)文件 在sql_mode中加入STRICT_TRANS_TABLES则表示开启 ...
- 使用IDEA打开工程未显示左侧工程目录栏
1. 重启IDEA2. 删除要打开的项目文件夹下的.idea文件夹3. open打开项目即可 注意: 是重启IDEA,不是只关闭IDEA的单个窗口 参考: https://blog.csdn.net/ ...
- string中的erase()函数
erase()是对string类型的字符串进行删除元素操作的函数 1.erase(int index) 删除下标从index开始直到字符串结尾的元素 1 string s = "123215 ...
- xticks,yticks
原本的图片如下所示: 如果加上这样的语句: import matplotlib.pyplot as plt plt.xticks([]),plt.yticks([]) 显示结果就为:
- LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)
21. 合并两个有序链表 21. Merge Two Sorted Lists 题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. LeetCode ...
- STL源码剖析——空间配置器Allocator#3 自由链表与内存池
上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...
- 链表习题(1)-设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
/*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/ /* 算法思想:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点, 则显然有f(L->next,x)的 ...
- python 之 前端开发(CSS三大特性、字体属性、文本属性、背景属性)
11.38 css三大特性 11.381 继承性 1.定义:给某一个元素设置一些属性,该元素的后代也可以使用,这个我们就称之为继承性2.注意: 1.只有以color.font-.text-.l ...
- C++11<functional>深度剖析:背景、原理、接口与实现
自C++11以来,C++标准每3年修订一次.C++14/17都可以说是更完整的C++11:即将到来的C++20也已经特性完整了. C++11已经有好几年了,它的年龄比我接触C++的时间要长10倍不止吧 ...