Code Practice Journal | Day 56_Graph06

KamaCoder 107. 寻找存在的路径

题目:107. 寻找存在的路径 (kamacoder.com)
题解:代码随想录 (programmercarl.com)

solution
class Program
{
    public static void Main(string[] args)
    {
        string[] dimensions = Console.ReadLine().Split();
        int n = int.Parse(dimensions[0]);
        int m = int.Parse(dimensions[1]);

        DSU dsu = new DSU(n);

        for (int i = 0; i < m; i++)
        {
            string[] nums = Console.ReadLine().Split();
            int x = int.Parse(nums[0]) - 1;
            int y = int.Parse(nums[1]) - 1;

            dsu.union(x, y);
        }

        string[] nodes = Console.ReadLine().Split();
        Console.WriteLine(dsu.find(int.Parse(nodes[0]) - 1) == dsu.find(int.Parse(nodes[1]) - 1) ? 1 : 0);
    }
}

class DSU
{
    int[] dsu;

    public DSU(int size)
    {
        dsu= new int[size];
        for (int i = 0; i < size; i++)
        {
            dns[i] = i;
        }
    }

    public int find(int num)
    {
        if (dsu[num] != num)
        {
            dsu[num] = find(dsu[num]);
        }
        return dsu[num];
    }

    public void union(int x, int y)
    {
        int rootx = find(x);
        int rooty = find(y);

        if (rootx != rooty)
        {
            dsu[rootx] = y;
        }
    }
}

KamaCoder 108. 冗余连接

题目:108. 冗余连接 (kamacoder.com)
题解:代码随想录 (programmercarl.com)

solution
class Program
{
    public static void Main(string[] args)
    {
        int num1 = 0;
        int num2 = 0;
        string N = Console.ReadLine();
        int n = int.Parse(N);

        DSU dsu = new DSU(n);

        for (int i = 0; i < n; i++)
        {
            string[] nums = Console.ReadLine().Split();
            int x = int.Parse(nums[0]) - 1;
            int y = int.Parse(nums[1]) - 1;
            if (dsu.union(x, y))
            {
                num1 = x;
                num2 = y;
            }
        }

        Console.WriteLine(string.Join(" ", num1 + 1, num2 + 1));
    }
}

class DSU
{
    int[] dsu;

    public DSU(int size)
    {
        dsu = new int[size];
        for (int i = 0; i < size; i++)
        {
            dsu[i] = i;
        }
    }

    public int find(int num)
    {
        if (dsu[num] != num)
        {
            dsu[num] = find(dsu[num]);
        }
        return dsu[num];
    }

    public bool union(int x, int y)
    {
        int rootx = find(x);
        int rooty = find(y);

        if (rootx != rooty)
        {
            dsu[rootx] = y;
            return false;
        }
        else return true;
    }
}
summary

key:

(成环)删除的边:构成边的两个节点具有相同的根

改造union函数:遇到需要删除的边则记录节点,否则将边加入并查集

KamaCoder 107. 冗余连接Ⅱ

题目:109. 冗余连接II (kamacoder.com)
题解:代码随想录 (programmercarl.com)

solution
class Program
{
    public static void Main(string[] args)
    {
        //处理输入
        //  维度
        string N = Console.ReadLine();
        int n = int.Parse(N);
        // 数组
        int[][] edges = new int[n + 1][];
        for (int i = 1; i <= n; i++)
        {
            string[] nodes = Console.ReadLine().Split();
            edges[i][0] = int.Parse(nodes[0]);
            edges[i][1] = int.Parse(nodes[1]);
        }

        //初始化
        // 可能的双父节点
        int[] candi1 = null;
        int[] candi2 = null;
        // dsu数组
        DSU dsu = new DSU(n + 1);

        //检查双父节点并拆分
        foreach (int[] edge in edges)
        {
            int parent = edge[0];
            int child = edge[1];
            if (dsu.dsu[child] != child)
            {
                // 原边
                candi1 = new int[] { dsu.dsu[child], child };
                // 新边
                candi2 = new int[] { parent, child };
                // 拆分
                edge[1] = 0;
            }
            else
            {
                dsu.dsu[child] = parent;
            }
        }

        //检查环
        // 重新初始化
        for (int i = 0; i <= n; i++)
        {
            dsu.dsu[i] = i;
        }
        foreach (int[] edge in edges)
        {
            if (edge[1] == 0) continue;
            int parent = edge[0];
            int child = edge[1];
            if (!dsu.union(parent, child))
            {
                if (candi1 == null)
                {
                    Console.WriteLine($"{parent} {child}");
                }
                else
                {
                    Console.WriteLine($"{candi1[0]} {candi2[1]}");
                }
                return;
            }
        }
        Console.WriteLine($"{candi2[0]} {candi2[1]}");

    }
}

public class DSU
{
    public int[] dsu;

    public DSU(int size)
    {
        dsu = new int[size];
        for (int i = 0; i < size; i++)
        {
            dsu[i] = i;
        }
    }

    public int find(int num)
    {
        if (dsu[num] != num)
        {
            dsu[num] = find(dsu[num]);
        }
        return dsu[num];
    }

    public bool union(int x, int y)
    {
        int rootx = find(x);
        int rooty = find(y);

        if (rootx == rooty) return false;
        else
        {
            dsu[y] = x;
            return true;
        }
    }
}
summary

两种冗余情况:

1、一个节点存在两个父节点

2、存在环

清除冗余策略:

1、记录每个节点的父节点,如果存在则分别记录两条边

2、使用并查集检测环

3、判断情况:
若不存在双父节点:直接处理环
若存在双父节点:分别尝试删除两条边

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值