蓝桥杯_算法训练_安慰奶牛(用Kruskal、Prim算法分别实现)
来源:互联网 发布:python mobi 下载 编辑:程序博客网 时间:2024/06/06 04:17
问题描述
Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路。
道路被用来连接N个牧场,牧场被连续地编号为1到N。每一个牧场都是一个奶牛的家。
FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性。
你首先要决定那些道路是需要保留的N-1条道路。
第j条双向道路连接了牧场Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的时间。
没有两个牧场是被一条以上的道路所连接。
奶牛们非常伤心,因为她们的交通系统被削减了。
你需要到每一个奶牛的住处去安慰她们。每次你到达第i个牧场的时候(即使你已经到过),你必须花去Ci的时间和奶牛交谈。
你每个晚上都会在同一个牧场(这是供你选择的)过夜,直到奶牛们都从悲伤中缓过神来。
在早上 起来和晚上回去睡觉的时候,你都需要和在你睡觉的牧场的奶牛交谈一次。
这样你才能完成你的 交谈任务。假设Farmer John采纳了你的建议,请计算出使所有奶牛都被安慰的最少时间。
输入格式
第1行包含两个整数N和P。
接下来N行,每行包含一个整数Ci。
接下来P行,每行包含三个整数Sj, Ej和Lj。
输出格式
输出一个整数, 所需要的总时间(包含和在你所在的牧场的奶牛的两次谈话时间)。
样例输入
5 6
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6
样例输出
176
数据规模与约定
5 <= N <= 10000,N-1 <= P <= 100000,0 <= Lj <= 1000,1 <= Ci <= 1,000。
Kruskal算法简述:
假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:
先构造一个只含 n 个顶点,而边集为空的子图,
若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。
之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,
也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,
而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。
import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.Scanner;import java.util.function.Function;import java.util.function.ToDoubleFunction;import java.util.function.ToIntFunction;import java.util.function.ToLongFunction;/** * @author 翔 * */public class Main { private static int nodeNum;//节点个数 private static int edgeNum;//边数 private static int[] C;//节点权值 private static int Cmin;//最小节点权值 private static ArrayList<Edge> edges=new ArrayList<Edge>();//边集合 private static ArrayList<Edge> Enew=new ArrayList<Edge>();//Kruskal算法中的Enew private static int[] root;//root[i]:代表i节点所在树对应的根节点 /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub init(); kruskal(); System.out.println(caculate()); } //计算所需要的总时间 private static int caculate(){ int sum=0; for(int i=0;i<Enew.size();i++){ sum+=Enew.get(i).weight; } return sum+Cmin; } //Kruskal算法的主要步骤 private static void kruskal(){ for(int i=0;i<edges.size()&&Enew.size()<nodeNum-1;i++){ Edge edge=edges.get(i); if(!inSameTree(edge.from,edge.to)){ Enew.add(edge); root[edge.to]=root[edge.from]; } } } //判断两个顶点是否在同一棵树里 private static boolean inSameTree(int from,int to){ if(findRoot(from)==findRoot(to)){ return true; }else{ return false; } } //寻找某节点的根节点 private static int findRoot(int i){ if(root[i]==i){ return i; }else{ return root[i]=findRoot(root[i]); } } //初始化各参数的值 private static void init(){ Scanner sc=new Scanner(System.in); nodeNum=sc.nextInt(); edgeNum=sc.nextInt(); C=new int[nodeNum+1]; root=new int[nodeNum+1]; for(int i=1;i<=nodeNum;i++){ C[i]=sc.nextInt(); root[i]=i; } findCmin();//寻找出最小节点权值 for(int i=0;i<edgeNum;i++){ Edge edge=new Edge(sc.nextInt(),sc.nextInt(),sc.nextInt()); edges.add(edge); } //重新计算边权!!!!重点!!!!!!!!!!!! for(int i=0;i<edgeNum;i++){ edges.get(i).weight=edges.get(i).weight*2+C[edges.get(i).from]+C[edges.get(i).to]; } Collections.sort(edges,new EdgeComparator());//按照权值对边集合排序 sc.close(); } //寻找出最小节点权值 private static void findCmin(){ int min=C[1]; for(int i=2;i<=nodeNum;i++){ if(C[i]<min){ min=C[i]; } } Cmin=min; }}class Edge{ int from; int to; int weight; public Edge(int from,int to,int weight){ this.from=from; this.to=to; this.weight=weight; }}class EdgeComparator implements Comparator<Edge>{ public int compare(Edge arg0, Edge arg1) { // TODO Auto-generated method stub return arg0.weight-arg1.weight; } public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> arg0) { // TODO Auto-generated method stub return null; } public static <T, U> Comparator<T> comparing( Function<? super T, ? extends U> arg0, Comparator<? super U> arg1) { // TODO Auto-generated method stub return null; } public static <T> Comparator<T> comparingDouble( ToDoubleFunction<? super T> arg0) { // TODO Auto-generated method stub return null; } public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> arg0) { // TODO Auto-generated method stub return null; } public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> arg0) { // TODO Auto-generated method stub return null; } public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { // TODO Auto-generated method stub return null; } public static <T> Comparator<T> nullsFirst(Comparator<? super T> arg0) { // TODO Auto-generated method stub return null; } public static <T> Comparator<T> nullsLast(Comparator<? super T> arg0) { // TODO Auto-generated method stub return null; } public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { // TODO Auto-generated method stub return null; } public Comparator<Edge> reversed() { // TODO Auto-generated method stub return null; } public Comparator<Edge> thenComparing(Comparator<? super Edge> arg0) { // TODO Auto-generated method stub return null; } public <U extends Comparable<? super U>> Comparator<Edge> thenComparing( Function<? super Edge, ? extends U> arg0) { // TODO Auto-generated method stub return null; } public <U> Comparator<Edge> thenComparing( Function<? super Edge, ? extends U> arg0, Comparator<? super U> arg1) { // TODO Auto-generated method stub return null; } public Comparator<Edge> thenComparingDouble( ToDoubleFunction<? super Edge> arg0) { // TODO Auto-generated method stub return null; } public Comparator<Edge> thenComparingInt(ToIntFunction<? super Edge> arg0) { // TODO Auto-generated method stub return null; } public Comparator<Edge> thenComparingLong(ToLongFunction<? super Edge> arg0) { // TODO Auto-generated method stub return null; }}
Prim算法简述
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew= {x},其中x为集合V中的任一节点(起始点),Enew= {},为空;
3).重复下列操作,直到Vnew= V:
a.在集合E中选取权值最小的边
import java.util.ArrayList;import java.util.Scanner;/** * @author 翔 * */public class Main { private static int nodeNum;//节点个数 private static int edgeNum;//边数 private static int[] C;//节点权值 private static int Cmin;//最小节点权值 private static ArrayList<Edge> edges=new ArrayList<Edge>();//边集合 private static ArrayList<Edge> Enew=new ArrayList<Edge>();//Prim算法中的Enew private static ArrayList<Integer> V_Vnew=new ArrayList<Integer>();//Prim算法中的V-Vnew private static ArrayList<Integer> Vnew=new ArrayList<Integer>();//Prim算法中的Vnew /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub init(); prim(); System.out.println(caculate()); } //计算所需要的总时间 private static int caculate(){ int sum=0; for(int i=0;i<Enew.size();i++){ sum+=Enew.get(i).weight; } return sum+Cmin; } //Prim算法的主要步骤 private static void prim(){ for(int i=2;i<=nodeNum;i++){ int min=Integer.MAX_VALUE; Edge temp=null; for (int j = 0; j < edges.size(); j++) { if (((V_Vnew.contains(edges.get(j).from) && Vnew.contains(edges.get(j).to)) || (Vnew.contains(edges.get(j).from) && V_Vnew.contains(edges.get(j).to))) && edges.get(j).weight < min) { temp = edges.get(j); min = temp.weight; } } if(V_Vnew.contains(temp.to)){ V_Vnew.remove(new Integer(temp.to)); Vnew.add(temp.to); }else{ V_Vnew.remove(new Integer(temp.from)); Vnew.add(temp.from); } edges.remove(temp); Enew.add(temp); } } //初始化各参数的值 private static void init(){ Scanner sc=new Scanner(System.in); nodeNum=sc.nextInt(); edgeNum=sc.nextInt(); C=new int[nodeNum+1]; for(int i=1;i<=nodeNum;i++){ C[i]=sc.nextInt(); V_Vnew.add(i); } int CminFlag=findCmin();//寻找出C[]数组中值最小的数对应的下标 V_Vnew.remove(new Integer(CminFlag)); Vnew.add(CminFlag); for(int i=0;i<edgeNum;i++){ Edge edge=new Edge(sc.nextInt(),sc.nextInt(),sc.nextInt()); edges.add(edge); } //重新计算边权!!!!重点!!!!!!!!!!!! for(int i=0;i<edgeNum;i++){ edges.get(i).weight=edges.get(i).weight*2+C[edges.get(i).from]+C[edges.get(i).to]; } sc.close(); } //寻找出C[]数组中值最小的数对应的下标 private static int findCmin(){ int min=C[1]; int flag=1; for(int i=2;i<=nodeNum;i++){ if(C[i]<min){ min=C[i]; flag=i; } } Cmin=min; return flag; }}class Edge{ int from; int to; int weight; public Edge(int from,int to,int weight){ this.from=from; this.to=to; this.weight=weight; }}
- 蓝桥杯_算法训练_安慰奶牛(用Kruskal、Prim算法分别实现)
- 蓝桥杯 算法训练 安慰奶牛 (kruskal)
- 蓝桥杯 算法训练 安慰奶牛
- 蓝桥杯 算法训练 安慰奶牛
- 蓝桥杯 算法训练 安慰奶牛
- 算法训练 安慰奶牛 蓝桥杯
- 蓝桥杯-算法训练-安慰奶牛
- 蓝桥杯_算法训练_节点选择(用Dijkstra,Bellman-Ford,SPFA算法分别实现)
- 算法训练 安慰奶牛
- 安慰奶牛 (算法训练)
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 算法训练 安慰奶牛
- 蓝桥杯算法训练——安慰奶牛(最小生成树+kruskal)
- 冒泡排序
- iframe页面缓存加载
- 使用Cocos构建一个完整项目
- C++中string类详解
- [Java] 常用方法的解释
- 蓝桥杯_算法训练_安慰奶牛(用Kruskal、Prim算法分别实现)
- stackoverflow转载(关于对attributeSet理解)
- MVC学生管理
- centos log4cxx编译安装
- 路由器和网关的区别?
- equalsIgnoreCase()和equals()以及'=='的区别以及使用,
- dom4j 新增节点 自动出现xmlns=""
- 《Python绝技:运用Python成为顶级黑客》试读感想
- BZOJ_P1318 [SPOJ744] Longest Permutation(单调栈)