求最小生成樹可以使用Prim或Kruskal算法
Kruskal比較直觀,因爲邊是按全局從小到大依次考慮的,所以能保證全局最優解。若不構成環,則加入這條邊;否則,丟棄這條邊。因爲出現環,說明當前已經有邊將該點加入生成樹,而越先考慮的邊代價是最小的。
Prim也是個貪心算法,但證明不太直觀。
下面是hdu 1875的java解
採用Kruskal算法,複雜度爲O(eloge),效率通常情況下都比Prim要高
使用並查集,帶路徑壓縮,所以每次集合方面的操作代價幾乎是常數
這題要使用double類型才能過!,還有回車符號得是/r/n.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Point {
private int x;
private int y;
private int id;
private Point parent = this;
public Point(int newId) {
this.id = newId;
this.x = -1;
this.y = -1;
}
public Point(int newX, int newY) {
this.x = newX;
this.y = newY;
this.id = -1;
}
final public int getX() {
return this.x;
}
final public int getY() {
return this.y;
}
final public int getId(){
return this.id;
}
public Point getParent() {
return this.parent;
}
public void setParent(Point newParent) {
this.parent = newParent;
}
}
class Edge {
Point point1;
Point point2;
double weight;
public Edge(){
}
public Edge(Point newPoint1, Point newPoint2) {
this.point1 = newPoint1;
this.point2 = newPoint2;
this.weight = calWeight(this.point1, this.point2);
}
public Edge(int start, int end, double newWeight) {
this.point1 = new Point(start);
this.point2 = new Point(end);
this.weight = newWeight;
}
public double calWeight(Point point1, Point point2) {
int x1 = point1.getX();
int y1 = point1.getY();
int x2 = point2.getX();
int y2 = point2.getY();
return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
public Point getPoint1(){
return point1;
}
public Point getPoint2(){
return point2;
}
public double getWeight() {
return weight;
}
}
class MST {
private ArrayList<Point> points;
private ArrayList<Edge> edges;
private double cost = 0;
public MST() {
}
public MST(int newSize, boolean isEdge) {
if(!isEdge) {
this.points = new ArrayList<Point>(newSize);
this.edges = new ArrayList<Edge>();
} else {
this.edges = new ArrayList<Edge>(newSize);
}
}
final public void addPoint(Point newPoint){
this.points.add(newPoint);
}
final public void addEdge(Point point1, Point point2) {
Edge tmp = new Edge(point1, point2);
if(tmp.getWeight() >= 10 && tmp.getWeight() <= 1000) {
this.edges.add(tmp);
}
}
final public void addEdge(int start, int end, double weight) {
this.edges.add(new Edge(start, end, weight));
}
final public void buildEdges() {
for(int i = 0; i < points.size(); i++) {
for(int j = i+1; j < points.size(); j++) {
Point u = points.get(i);
Point v = points.get(j);
addEdge(u, v);
}
}
}
public double kruskal() {
Collections.sort(this.edges, new Comparator<Edge>() {
@Override
public int compare(Edge edge1, Edge edge2) {
double w1 = edge1.getWeight();
double w2 = edge2.getWeight();
if(w1 > w2) {
return 1;
} else {
return -1;
}
}
});
// for(Edge e : this.edges) {
// System.out.println(e.getWeight());
// }
for(int i = 0; i < this.edges.size(); i++) {
Edge edge = edges.get(i);
Point point1 = edge.getPoint1();
Point point2 = edge.getPoint2();
Point parent1 = findParent(point1);
Point parent2 = findParent(point2);
if(parent1 != parent2) {
this.cost += edge.getWeight();
parent2.setParent(parent1);
}
Point theParent = findParent(points.get(0));
for(int i = 1; i < this.points.size(); i++) {
Point tmpPoint = points.get(i);
if(findParent(tmpPoint) != theParent) {
return -1;
}
}
return this.cost;
}
public Point findParent(Point x) {
Point parent = x.getParent();
if( parent != x) {
Point newParent = findParent(parent);
x.setParent(newParent);
return newParent;
} else {
return parent;
}
}
public double getCost() {
return this.cost;
}
}
public class Main {
public static void main(String[] args) throws IOException {
int T, nodeCnt, x, y;
StreamTokenizer in = new StreamTokenizer(
new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
T = (int)in.nval;
for(int i = 0; i < T; i++) {
in.nextToken();
nodeCnt = (int)in.nval;
MST mst = new MST(nodeCnt, false);
for(int j = 0; j < nodeCnt; j++) {
in.nextToken();
x = (int)in.nval;
in.nextToken();
y = (int)in.nval;
mst.addPoint(new Point(x,y));
}
mst.buildEdges();
double res = mst.kruskal();
if(res != -1) {
out.printf("%.1f\r\n", 100*res);
} else {
out.println("oh!");
}
// out.flush();
}
out.flush();
}
}