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;
    }

    
}
相关推荐
apcipot_rain8 分钟前
C++转Java日记(10)
java·开发语言
总要学点什么1 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
简 洁 冬冬1 小时前
泛型方法写法全面辨析:从「能编译」到「能跑」到「能用」
java·泛型
YLCHUP1 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
LGL6030A1 小时前
Java学习历程31——初识Spring Boot
java·spring boot·学习
xiaoye-duck1 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀1 小时前
背包DP(01背包+完全背包)
c++·算法
Funlang2 小时前
龙芯上的 Fun:从跑起来到机器码
开发语言·龙芯
总要学点什么2 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
笑容掩饰我的失落3 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法