day 54 图论part6

文章目录

  • [108. 多余的边](#108. 多余的边)
  • [109. 多余的边II](#109. 多余的边II)

108. 多余的边

无向图,直接用并查集判断是否成环就可以。

java 复制代码
import java.util.Scanner;

public class Main {
    private static int[] father;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int pointNum = scanner.nextInt();
        father = new int[pointNum + 1];
        init();
        for (int i = 0; i < pointNum; i++) {
            join(scanner.nextInt(), scanner.nextInt());
        }
    }

    /**
     * 并查集初始化
     */
    private static void init() {
        for (int i = 1; i < father.length; i++) {
            // 让每个元素指向自己
            father[i] = i;
        }
    }

    /**
     * 并查集寻根
     *
     * @param u
     * @return
     */
    private static int find(int u) {
        // 判断 u 是否等于自己,如果是的话,直接返回自己
        // 如果不等于自己,就寻找根,寻找的时候,反复进行路径压缩
        return u == father[u] ? u : (father[u] = find(father[u]));
    }

    /**
     * 判断 u 和 v 是否同根
     *
     * @param u
     * @param v
     * @return
     */
    private static boolean isSame(int u, int v) {
        return find(u) == find(v);
    }

    /**
     * 添加 边 到并查集,v 指向 u
     *
     * @param u
     * @param v
     */
    private static void join(int u, int v) {
        // --if-- 如果两个点已经同根,说明他们的信息已经存储到并查集中了,直接返回即可
        // 寻找u的根
        int uRoot = find(u);
        // 寻找v的根
        int vRoot = find(v);
        if (uRoot == vRoot) {
            // --if-- 如果u,v的根相同,说明两者已经连接了,直接输出
            System.out.println(u + " " + v);
            return;
        }
        // --if-- 将信息添加到并查集
        father[vRoot] = uRoot;
    }

}

109. 多余的边II

有向图,一共有三种情况,图中存在入度为2的节点,需要删除一条边,但是删除后要保证不成环,另外一种情况就是成环,没有节点入度为2。

java 复制代码
import java.util.*;

class Main {
    public static int N;
    static DisJoint disjoint;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        disjoint = new DisJoint(N + 1);
         List<Edge> edges = new ArrayList<>();
         int[] indegree = new int[N + 1];

         for (int i = 0; i < N; i++) {
            int s = sc.nextInt();
            int t = sc.nextInt();
            Edge edge = new Edge(s, t);
            edges.add(edge);
            indegree[t]++;
         }
         List<Integer> vec = new ArrayList<>();
         for (int i = 0; i < N; i++) {
            if (indegree[edges.get(i).t] == 2) {
                vec.add(i);
            }
         }
         if (vec.size() > 0) {
            if (isTreeAfterDelete(edges, vec.get(1))) {
                System.out.println(edges.get(vec.get(1)).s + " " + edges.get(vec.get(1)).t);
            }
            else {
                System.out.println(edges.get(vec.get(0)).s + " " + edges.get(vec.get(0)).t);
            }
            return;
         }
         for (int i = 0; i < N; i++) {
            if (disjoint.isSame(edges.get(i).s, edges.get(i).t)) {
                System.out.println(edges.get(i).s + " " + edges.get(i).t);
            }
            else {
                disjoint.join(edges.get(i).s, edges.get(i).t);
            }
         }
    }


    public static boolean isTreeAfterDelete(List<Edge> edges, Integer v) {
        disjoint = new DisJoint(N + 1);
        for (int i =0; i < N; i++) {
            if (i == v) {
                continue;
            }
            if (disjoint.isSame(edges.get(i).s, edges.get(i).t)) {
                return false;
            }
            else {
                disjoint.join(edges.get(i).s, edges.get(i).t);
            }
        }
        return true;
    }
}

class Edge {
    int s;
    int t;
    public Edge(int s, int t) {
        this.s = s;
        this.t = t;
    }
}
class DisJoint {
    private int[] father;

    public DisJoint(int N) {
        father = new int[N + 1];
        for (int i = 0; i < N; i ++) {
            father[i] = i;
        }
    }
    public int find(int n) {
        return father[n] == n ? n : (father[n] = find(father[n]));
    }
    public void join(int n, int m) {
        n = find(n);
        m = find(m);
        if (n == m) {
            return;
        }
        father[n] = m;
    }
    public boolean isSame(int n, int m) {
        n = find(n);
        m = find(m);
        return n == m;
    }

    
}
相关推荐
天若有情6731 小时前
用编程思维重构学习:从IoC到响应式,打造高效知识体系
学习·算法·重构·ioc·学习方法·依赖注入·响应式数据
笨笨马甲1 小时前
Qt 嵌入式开发
开发语言·qt
深念Y1 小时前
Java并发集合:原理与使用场景速查
java·开发语言
恼书:-(空寄2 小时前
Spring Boot 实现事件监听(监听器+自定义事件)完整指南
java·spring boot·后端
khddvbe2 小时前
分布式日志系统实现
开发语言·c++·算法
Sinder_小德2 小时前
一款基于 Electron + Vue 3 的本地旅行地图相册桌面应用
开发语言·javascript·ecmascript
我真会写代码2 小时前
深入解析Java ArrayList与HashMap扩容机制:原理、差异与实战避坑
java·数据结构·算法·集合
不懒不懒2 小时前
【使用逻辑回归(Logistic Regression)算法对预处理后的数据集(平均值填充)进行分类任务训练与评估】
算法·分类·逻辑回归
星空2 小时前
python复习1
开发语言·python