当前位置: 代码迷 >> 综合 >> poj 3723 Conscription 最小生成树 Java
  详细解决方案

poj 3723 Conscription 最小生成树 Java

热度:60   发布时间:2024-02-24 13:10:44.0

poj 3723 Conscription
买一个人就可以利用一个关系(一条边),一开始买一个人肯定是要10000的,然后再买一个人就可以根据他之前买的那个人的关系进行减价,相当于一共买n个人的话,是利用到n - 1 条边,所以要构建最大生成树。然后每个人都要基本的10000块,所以答案就是每个人10000 然后减去最大生成树里的所有边的权重。

package 图论;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayDeque;
import java.util.PriorityQueue;public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static StreamTokenizer st = new StreamTokenizer(br);static int nextInt() throws IOException {
    st.nextToken();return (int)st.nval;}public static void main(String[] args) throws IOException {
    int t = nextInt();while (t-- > 0) {
    int n = nextInt(); // n 个女兵int m = nextInt(); // m 个男兵int r = nextInt(); // 相当于 r 条边PriorityQueue<Edge> pq = new PriorityQueue<Edge>();for (int i = 0; i < r; i++) {
    int v = nextInt(); // 女兵编号int w = nextInt() + n; // 注意:男兵编号要往后延,这里加的是 nint weight = nextInt(); // 男兵和女兵之间的关系Edge e = new Edge(v, w, weight);pq.add(e);}Kruskal kru = new Kruskal(n + m, pq);int ans = 0;for (Edge e : kru.queue) {
    ans += e.weight;}System.out.println(10000 * (n + m) - ans);}}
}class Edge implements Comparable<Edge> {
    int v;int w;double weight;public Edge(int v, int w, double weight) {
    this.v = v;this.w = w;this.weight = weight;}// 返回边的其中一个顶点int either() {
    return v;}// 返回与v不同的另一个顶点int other(int v) {
    if (v == this.w) {
    return this.v;}return this.w;}@Overridepublic int compareTo(Edge o) {
    return Double.compare(o.weight, this.weight);}
}class UnionFind {
    int[] parent;int[] size; // 根结点对应的分量的大小int count; // 连通分量的数量public UnionFind(int n) {
    parent = new int[n];size = new int[n];for (int i = 0; i < n; i++) {
    parent[i] = i;}for (int i = 0; i < n; i++) {
    size[i] = 1;}count = n;}int find(int p) {
    while (parent[p] != p) {
    p = parent[p];}return p;}boolean isConnected(int p, int q) {
    return find(p) == find(q);}void union(int p, int q) {
    int pRoot = find(p);int qRoot = find(q);if (pRoot == qRoot) {
    return;}// 让小的指向大的if (size[pRoot] < size[qRoot]) {
    parent[pRoot] = qRoot;size[qRoot] += size[pRoot];}else {
    parent[qRoot] = pRoot;size[pRoot] += size[qRoot];}count--;}
}class Kruskal {
    ArrayDeque<Edge> queue;  // 存放最小生成树中的边PriorityQueue<Edge> pq;int ver; // 顶点数public Kruskal(int ver, PriorityQueue<Edge> pq) {
    queue = new ArrayDeque<Edge>();this.ver = ver;this.pq = pq;UnionFind uf = new UnionFind(ver);while (! pq.isEmpty() && queue.size() < ver - 1) {
    Edge e = pq.poll();int v = e.either();int w = e.other(v);if (uf.isConnected(v, w)) {
    continue;}uf.union(v, w);queue.add(e);}}
}
  相关解决方案