图-Kruskal

package Week2;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
/*温迪有一个国家,他想建立一支军队来保护他的国家。他接了N个女孩和M个男孩,想把他们收起来当他的士兵。征集一个没有任何特权的士兵,
必须交1万元。女孩和男孩之间有一些关系,Windy可以利用这些关系来降低成本。如果女孩x和男孩y有关系d,其中一个已经被收走,
Windy可以用10000-d人民币来收另一个。
现在考虑到女孩和男孩之间的所有关系,你的任务是找到温迪必须支付的最少的钱。请注意,收集一个士兵时只能使用一个关系。 
输入的第一行是测试用例的数量。 
每个测试用例的第一行包含三个整数N、M和R。 
然后R行,每个包含三个整数Xi,Yi和Di。 
每个测试用例前都有一个空行。
对于每个测试用例,在一行中输出答案。*/

//71071
//54223
//2
//
//5 5 8
//4 3 6831
//1 3 4583
//0 0 6592
//0 1 3063
//3 3 4975
//1 3 2049
//4 2 2104
//2 2 781
//
//5 5 10
//2 4 9820
//3 2 6236
//3 1 8864
//2 4 8326
//2 0 5156
//2 0 1463
//4 1 2439
//0 4 4373
//3 4 8889
//2 4 3133
public class I_Kruskal {
    static int T;
    static int N,M,R;
    static NodeI nodes[];
    static List<NodeI> adjList;
    static int parent[];
    static int ans;
    static int costMax;
    public static void main(String[] args) throws Exception{
          System.setIn(new FileInputStream("Solution.txt"));
          BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
          StringTokenizer st = new StringTokenizer(br.readLine());
          T = Integer.parseInt(st.nextToken());
          for (int t = 1; t <= T; t++) {
            st = new StringTokenizer(br.readLine());
            if(!st.hasMoreTokens()) st = new StringTokenizer(br.readLine());

            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            R = Integer.parseInt(st.nextToken());
            parent = new int[N+M+2];
            nodes = new NodeI[R+2];
            //N个女孩,M个男孩总人数N+M个人,case坐标M人的时候变换一下,加个N值即不重复,每个坐标不重复即可以用并查集
            for (int i = 0; i <= N+M-1; i++) {
                parent[i] = i;
            }
            
            for (int i = 0; i < R; i++) {
                st = new StringTokenizer(br.readLine());
                int s = Integer.parseInt(st.nextToken());
                int e = Integer.parseInt(st.nextToken());
                int d = Integer.parseInt(st.nextToken());
                nodes[i]=new NodeI(s,N+e,d);
            }
            Arrays.sort(nodes, 0, R, new Comparator<NodeI>() {

                @Override
                public int compare(NodeI o1, NodeI o2) {
                    return o2.d-o1.d;
                }
            });;
            ans = 0;
            costMax = 0;
            for (int i = 0; i < R; i++) {
                if(find(nodes[i].s)!=find(nodes[i].e)) {
                    union(nodes[i].s,nodes[i].e);
                    costMax = costMax+nodes[i].d;
                }
            }
            ans = (N+M)*10000-costMax;//雇佣N+M个员工,总共10000*(M+N),通过雇佣关系减去D可以省的钱
            System.out.println(ans);
            
          }
    }
  
  public static void union(int a,int b) {
        int x = find(a);
        int y = find(b);
        if(x==y) {
            return;
        }
        if(x<y) {
            parent[y]=x;
        }
        if(x>y) {
            parent[x]=y;
        }
    }
    
    public static int find(int i) {
        if(i==parent[i]) {
            return i;
        }
        return parent[i]=find(parent[i]);
    }
}

class NodeI {
    int s;
    int e;
    int d;
    public NodeI(int s,int e,int d) {
        this.s=s;
        this.e = e;
        this.d = d;
    }
    
    
}
View Code

 

package Week2;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
//安德鲁正在做系统管理员,并计划在他的公司建立一个新的网络。公司将有N个集线器,它们可以通过电缆相互连接。由于公司的每个员工都必须能够访问整个网络,
//因此每个集线器必须可以通过其他集线器(可能有一些中间集线器)的电缆访问
//由于可以使用不同类型的电缆,而且较短的电缆更便宜,因此有必要制定这样的集线器连接计划,使单个电缆的最大长度最小。
//还有另一个问题-由于兼容性问题和建筑几何体限制,不是每个中心都可以连接到任何其他中心。
//当然,Andrew将为您提供有关可能的集线器连接的所有必要信息。您将帮助安德鲁找到连接集线器的方法,以便满足上述所有条件。

//求 首先输出集线器连接计划中单个电缆的最大长度。
//然后输出您的计划:首先输出P—使用的电缆数量,然后输出P对整数—相应电缆连接的集线器数量。用空格和/或换行符分隔数字。
//解题思路利用克鲁斯卡尔找到最小生成树,然后找的过程当中找到最小生成树的最大边的值,即所求单个电缆的最大长度
//把合并过程中的两条边加到list里即最小生成树所构成的边
//4 6
//1 2 1
//1 3 1
//1 4 2
//2 3 1
//3 4 1
//2 4 1
public class H_Kruskal {
    static int N,M;
    static NodeH nodes[];
    static List<NodeH> adjList;
    static int parent[];
    static int ans;
    static int edgeMax;
    public static void main(String[] args) throws Exception{
          System.setIn(new FileInputStream("Solution.txt"));
          BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
          StringTokenizer st = new StringTokenizer(br.readLine());
          N = Integer.parseInt(st.nextToken());
          M = Integer.parseInt(st.nextToken());
          parent = new int[N+1];
          nodes = new NodeH[M+1];
          adjList = new ArrayList<NodeH>();
          for (int i = 1; i <= N; i++) {
            parent[i]=i;
          }
          for (int i = 1; i <= M; i++) {
            st = new StringTokenizer(br.readLine());
            int s = Integer.valueOf(st.nextToken());
            int e = Integer.parseInt(st.nextToken());
            int len = Integer.parseInt(st.nextToken());
            nodes[i]=new NodeH(s,e,len);
          }
          
          Arrays.sort(nodes, 1, M+1, new Comparator<NodeH>() {
            @Override
            public int compare(NodeH o1, NodeH o2) {
                return o1.len-o2.len;
            }
          });
          
          int selected = 0;
          ans = 0;
          edgeMax = 0;
          int size = 0;
          for (int i = 1; i <= M; i++) {
             if(find(nodes[i].s)!=find(nodes[i].e)) {
                 union(nodes[i].s,nodes[i].e);
                 size++;
                 adjList.add(nodes[i]);
                 edgeMax = Math.max(nodes[i].len, edgeMax);
                 selected++;
             }
          }
          if(selected == N-1) {
              System.out.println(edgeMax);
              System.out.println(size);
              for(int i=0;i<adjList.size();i++) {
                  int s = adjList.get(i).s;
                  int e = adjList.get(i).e;
                  System.out.println(s+" "+e);
              }
          }
          
    }
    
    public static void union(int a,int b) {
        int x = find(a);
        int y = find(b);
        if(x==y) {
            return;
        }
        if(x<y) {
            parent[y]=x;
        }
        if(x>y) {
            parent[x]=y;
        }
    }
    
    public static int find(int i) {
        if(i==parent[i]) {
            return i;
        }
        return parent[i]=find(parent[i]);
    }
}

class NodeH {
    int s;
    int e;
    int len;
    public NodeH(int s,int e,int len) {
        this.s=s;
        this.e = e;
        this.len = len;
    }
}
View Code

 

posted @ 2021-08-01 18:34  没带壳的蜗牛  阅读(21)  评论(0)    收藏  举报