算法笔记_164:算法提高 最小方差生成树(Java)
目录
1 问题描述
1 2 1
2 3 2
3 4 2
4 1 1
2 4 3
4 6
1 2 1
2 3 2
3 4 3
4 1 1
2 4 3
1 3 3
0 0
Case 2: 0.00
1<=U,V<=N<=50,N-1<=M<=1000,0<=W<=50。数据不超过5组。
2 解决方案
本题主要考查Kruskal算法,其中的重点在于并查算法的应用,在寻找最小平方差的最小生成树时,需要枚举边权值的均值。
但是,依照这样的方法,在蓝桥练习系统中测评一直为50分,在网上找了一下其他网友写的C代码,提交也是50分,可能是蓝桥练习系统的后台测试数据有点问题,也有可能是本题枚举的精确度不够。

具体代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner; public class Main {
public static int n, m;
public static double minV; //输入所有边中权值最小的边
public static double maxV; //输入所有边中权值最大的边
public static int[] id;
public static ArrayList<edge> map;
public static ArrayList<Double> result = new ArrayList<Double>(); class MyComparator implements Comparator<edge> {
public int compare(edge arg0, edge arg1) {
if(arg0.w > arg1.w)
return 1;
else if(arg0.w < arg1.w)
return -1;
return 0;
}
} static class edge {
public int a; //边的起点
public int b; //边的终点
public double v; //边的权值
public double w; //边权的方差值 public edge(int a, int b, double v) {
this.a = a;
this.b = b;
this.v = v;
this.w = 0;
}
} public void init() {
minV = Double.MAX_VALUE;
maxV = Double.MIN_VALUE;
map = new ArrayList<edge>();
} public int find(int a) {
int root = a;
while(id[root] >= 0) {
root = id[root];
}
int k = a, i;
while(k != root) {
i = id[k];
id[k] = root;
k = i;
}
return root;
} public void union(int a, int b) {
int rootA = find(a);
int rootB = find(b);
if(rootA == rootB)
return;
int num = id[rootA] + id[rootB];
if(id[rootA] < id[rootB]) {
id[rootB] = rootA;
id[rootA] = num;
} else {
id[rootA] = rootB;
id[rootB] = num;
}
} public void getResult() {
double avg = minV;
double minResult = Double.MAX_VALUE;
for(;avg <= maxV;avg = avg + 0.3) { //此处是解决本题的关键,即枚举最小生成树的边权的均值
for(int i = 0;i < map.size();i++) {
double v = map.get(i).v - avg;
map.get(i).w = v * v;
}
Collections.sort(map, new MyComparator());
id = new int[n + 1];
for(int i = 1;i <= n;i++)
id[i] = -1;
double sum = 0;
double[] value = new double[n - 1];
int count = 0;
for(int i = 0;i < map.size();i++) {
int rootA = find(map.get(i).a);
int rootB = find(map.get(i).b);
if(rootA != rootB) {
union(map.get(i).a, map.get(i).b);
value[count++] = map.get(i).v;
sum += map.get(i).v;
if(count == n - 1)
break;
}
}
sum = sum / (n - 1);
double temp = 0;
for(int i = 0;i < value.length;i++) {
temp = temp + (value[i] - sum) * (value[i] - sum);
}
temp = temp / (n - 1);
if(minResult > temp)
minResult = temp;
}
result.add(minResult);
} public static void main(String[] args) {
Main test = new Main();
Scanner in = new Scanner(System.in);
while(true) {
n = in.nextInt();
m = in.nextInt();
if(n == 0 || m == 0)
break;
test.init();
for(int i = 1;i <= m;i++) {
int a = in.nextInt();
int b = in.nextInt();
double v = in.nextDouble();
map.add(new edge(a, b, v));
minV = Math.min(minV, v);
maxV = Math.max(maxV, v);
}
test.getResult();
}
for(int i = 0;i < result.size();i++) {
System.out.print("Case "+(i+1)+": ");
System.out.printf("%.2f", result.get(i));
System.out.println();
}
}
}
算法笔记_164:算法提高 最小方差生成树(Java)的更多相关文章
- 算法提高 最小方差生成树(Kruskal)_模板
算法提高 最小方差生成树 时间限制:1.0s 内存限制:256.0MB 问题描述 给定带权无向图,求出一颗方差最小的生成树. 输入格式 输入多组测试数据.第一行为N,M,依次是 ...
- Java实现 蓝桥杯 算法提高最小方差生成树
1 问题描述 给定带权无向图,求出一颗方差最小的生成树. 输入格式 输入多组测试数据.第一行为N,M,依次是点数和边数.接下来M行,每行三个整数U,V,W,代表连接U,V的边,和权值W.保证图连通.n ...
- [loj2469]最小方差生成树
2018年论文题 约定:令点集$V=[1,n]$.边集$E=[1,m]$,记$m$条边依次为$e_{i}=(x_{i},y_{i},c_{i})$(其中$1\le i\le m$),将其按照$c_{i ...
- 算法笔记_165:算法提高 道路和航路(Java)
目录 1 问题描述 2解决方案 1 问题描述 问题描述 农夫约翰正在针对一个新区域的牛奶配送合同进行研究.他打算分发牛奶到T个城镇(标号为1..T),这些城镇通过R条标号为(1..R)的道路和P条 ...
- 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流
最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...
- 算法笔记_155:算法提高 概率计算(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出格式 输出一行 ...
- 算法笔记_167:算法提高 矩阵翻转(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 Ciel有一个N*N的矩阵,每个格子里都有一个整数. N是一个奇数,设X = (N+1)/2.Ciel每次都可以做这样的一次操作:他从矩阵 ...
- 算法笔记_166:算法提高 金属采集(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 人类在火星上发现了一种新的金属!这些金属分布在一些奇怪的地方,不妨叫它节点好了.一些节点之间有道路相连,所有的节点和道路形成了一棵树.一共 ...
- 算法笔记_163:算法提高 最大乘积(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 对于n个数,从中取出m个数,如何取使得这m个数的乘积最大呢? 输入格式 第一行一个数表示数据组数 每组输入数据共2行: 第1行给出总共的数 ...
随机推荐
- Windows 下使用 mingw+msys 交叉编译 Android Unity Mono
对于没有升级到 Unity5.4的用户,发布安卓版本都会有对 C# 脚本进行加密的需求,我们项目在裸奔了很长时间后,决定开始做这件事. 网上查看了很多资料,我很希望直接在 windows 下编译而不去 ...
- Linux基础系列-Day2
基础命令(文件内容管理) 1.cat:在当前终端显示文本文件内容 格式:cat [文件路径] -n 从1开始对所有输出的行数编号 -b 和-n相似,只不过对于空白行不编号:2.head:从文件内容开头 ...
- Python 头文件和常用函数
#coding=utf-8 """ @version: ?? @author: Donny @Mail: wdm666666@gmail.com @license: La ...
- BZOJ 1588 [HNOI2002]营业额统计(双向链表)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1588 [题目大意] 给出一个数列,对于每个数,选择其前面的某个数作差取绝对值, 使得所 ...
- 【贪心】【multiset】Tinkoff Challenge - Final Round (Codeforces Round #414, rated, Div. 1 + Div. 2) C. Naming Company
考虑两个人,先把各自的集合排个序,丢掉一半,因为比较劣的那一半一定用不到. 然后贪心地放,只有两种决策,要么把一个最优的放在开头,要么把一个最劣的放在结尾. 如果我的最优的比对方所有的都劣(或等于), ...
- Java学习笔记(12)
eclipse使用的步骤: 1.选择工作目录.以后在Eclipse上面写的所有代码都是在工作目录上的 2.在Project Exploer窗口上新建一个工程,以后我们写代码都是以工程为单位的 3.在工 ...
- kosaraju算法求强连通分量
什么是强连通分量?在这之前先定义一个强连通性(strong connectivity)的概念:有向图中,如果一个顶点s到t有一条路径,t到s也有一条路径,即s与t互相可达,那么我们说s与t是强连通的. ...
- [转]ssm整合1(环境搭建)
1 MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建http://blog.csdn.net/zhshulin/article/details/307798732 apache-m ...
- mysql启动错误解决
mysql 启动时,报错一般都不明显,因此我们需要配置错误日志 #vim /etc/my.cnf xxxxxxxxxx 1 1 #vim /etc/my.cnf 在[mysqld]下添加 log_ ...
- ObjC的initialize和init
Objective-C很有趣的一个地方是,它非常非常像C.实际上,它就是C语言加上一些其他扩展和一个运行时间(runtime). 有了这个在每个Objective-C程序中都会起作用的附加运行时间,给 ...