예제 #1
0
    static void Main()
    {
        Console.SetOut(new System.IO.StreamWriter(Console.OpenStandardOutput())
        {
            AutoFlush = false
        });
        var h = Read();
        int n = h[0], qc = h[1];
        var qs = Array.ConvertAll(new bool[qc], _ => Read());

        var uf = new UF(n);

        foreach (var q in qs)
        {
            if (q[0] == 0)
            {
                uf.Unite(q[1], q[2]);
            }
            else
            {
                Console.WriteLine(uf.AreUnited(q[1], q[2]) ? 1 : 0);
            }
        }
        Console.Out.Flush();
    }
예제 #2
0
    static void Main()
    {
        var h  = Read();
        var n  = h[0];
        var ab = new int[h[1]].Select(_ => Read()).ToArray();
        var cd = new int[h[2]].Select(_ => Read()).ToArray();

        var uf = new UF(n + 1);

        foreach (var x in ab)
        {
            uf.Unite(x[0], x[1]);
        }

        var roots = Enumerable.Range(0, n + 1).GroupBy(uf.GetRoot).ToDictionary(g => g.Key, g => g.Count());
        var c     = Enumerable.Range(0, n + 1).Select(uf.GetRoot).Select(x => roots[x] - 1).ToArray();

        foreach (var x in ab)
        {
            c[x[0]]--;
            c[x[1]]--;
        }
        foreach (var x in cd)
        {
            if (!uf.AreUnited(x[0], x[1]))
            {
                continue;
            }
            c[x[0]]--;
            c[x[1]]--;
        }
        Console.WriteLine(string.Join(" ", c.Skip(1)));
    }
예제 #3
0
    static object Solve()
    {
        var(n, m) = Read2();
        var es = Array.ConvertAll(new bool[m], _ => Read2());

        var uf = new UF(n + 1);
        var vs = new List <int>();

        foreach (var e in es)
        {
            if (uf.AreUnited(e.u, e.v))
            {
                vs.Add(e.u);
            }
            else
            {
                uf.Unite(e.u, e.v);
            }
        }

        if (vs.Select(uf.GetRoot).Distinct().Count() != vs.Count)
        {
            return(0);
        }
        if (uf.GroupsCount - 1 != vs.Count)
        {
            return(0);
        }
        return(MPow(2, vs.Count));
    }
예제 #4
0
    static void Main()
    {
        var n  = int.Parse(Console.ReadLine());
        var qc = int.Parse(Console.ReadLine());
        var qs = Array.ConvertAll(new bool[qc], _ => Read4());

        var roots = new int[n + 1];
        var d     = new long[n + 1];

        foreach (var(_, x, y, v) in qs.Where(q => q.t == 0).OrderBy(q => q.x))
        {
            if (roots[x] == -1)
            {
                roots[x] = x;
            }

            roots[y] = roots[x];
            d[y]     = v - d[x];
        }

        var uf = new UF(n + 1);

        Console.SetOut(new System.IO.StreamWriter(Console.OpenStandardOutput())
        {
            AutoFlush = false
        });
        foreach (var(t, x, y, v) in qs)
        {
            if (t == 0)
            {
                uf.Unite(x, y);
            }
            else
            {
                if (uf.AreUnited(x, y))
                {
                    var v0 = (x - roots[x]) % 2 == 0 ? v - d[x] : d[x] - v;
                    var vy = (y - roots[y]) % 2 == 0 ? d[y] + v0 : d[y] - v0;
                    Console.WriteLine(vy);
                }
                else
                {
                    Console.WriteLine("Ambiguous");
                }
            }
        }
        Console.Out.Flush();
    }
예제 #5
0
        // 連結な無向グラフから無向木を取り出します。
        static int[][] GetUndirectedTree(int n, int[][] ues)
        {
            var uf  = new UF(n);
            var res = new List <int[]>();

            foreach (var e in ues)
            {
                if (uf.AreUnited(e[0], e[1]))
                {
                    continue;
                }
                uf.Unite(e[0], e[1]);
                res.Add(e);
            }
            return(res.ToArray());
        }
예제 #6
0
    static Edge[] Kruskal(int n, Edge[] ues)
    {
        var uf  = new UF(n);
        var mes = new List <Edge>();

        foreach (var e in ues.OrderBy(e => e.cost))
        {
            if (uf.AreUnited(e.i, e.j))
            {
                continue;
            }
            uf.Unite(e.i, e.j);
            mes.Add(e);
        }
        return(mes.ToArray());
    }
예제 #7
0
    static int[][] Kruskal(int n, int[][] ues)
    {
        var uf  = new UF(n);
        var mes = new List <int[]>();

        foreach (var e in ues.OrderBy(e => e[2]))
        {
            if (uf.AreUnited(e[0], e[1]))
            {
                continue;
            }
            uf.Unite(e[0], e[1]);
            mes.Add(e);
        }
        return(mes.ToArray());
    }
예제 #8
0
    static void Main()
    {
        var(h, w) = Read2();
        var qc = int.Parse(Console.ReadLine());

        h += 2;
        w += 2;

        int ToId(int i, int j) => i * w + j;

        int[] Nexts(int id) => new[] { id + 1, id - 1, id + w, id - w };

        var u  = new bool[h * w];
        var uf = new UF(h * w);

        Console.SetOut(new System.IO.StreamWriter(Console.OpenStandardOutput())
        {
            AutoFlush = false
        });
        for (int k = 0; k < qc; k++)
        {
            var q = Read();
            if (q[0] == 1)
            {
                var(i, j) = (q[1], q[2]);
                var p = ToId(i, j);

                u[p] = true;
                foreach (var np in Nexts(p))
                {
                    if (u[np])
                    {
                        uf.Unite(p, np);
                    }
                }
            }
            else
            {
                var(ai, aj, bi, bj) = (q[1], q[2], q[3], q[4]);
                var a = ToId(ai, aj);
                var b = ToId(bi, bj);
                Console.WriteLine(u[a] && u[b] && uf.AreUnited(a, b) ? "Yes" : "No");
            }
        }
        Console.Out.Flush();
    }
예제 #9
0
    public static int[][] Kruskal(int n, int[][] ues)
    {
        var uf  = new UF(n);
        var mes = new List <int[]>();

        foreach (var e in ues.OrderBy(e => e[2]))
        {
            if (uf.AreUnited(e[0], e[1]))
            {
                continue;
            }
            uf.Unite(e[0], e[1]);
            mes.Add(e);
            // 実際の頂点数に注意。
            // あまり実行速度に影響しないようです。
            //if (mes.Count == n - 1) break;
        }
        return(mes.ToArray());
    }
예제 #10
0
    // Partitioning
    static (int[][], int[][]) GetUndirectedTree(int n, int[][] ues)
    {
        var uf   = new UF(n);
        var res  = new List <int[]>();
        var res2 = new List <int[]>();

        foreach (var e in ues)
        {
            if (uf.AreUnited(e[0], e[1]))
            {
                res2.Add(e);
            }
            else
            {
                uf.Unite(e[0], e[1]);
                res.Add(e);
            }
        }
        return(res.ToArray(), res2.ToArray());
    }
예제 #11
0
    static void Main()
    {
        Func <int[]> read = () => Console.ReadLine().Split().Select(int.Parse).ToArray();
        var          h    = read();

        var uf = new UF(h[0]);
        var l  = new List <string>();

        foreach (var q in new int[h[1]].Select(_ => read()))
        {
            if (q[0] == 0)
            {
                uf.Unite(q[1], q[2]);
            }
            else
            {
                l.Add(uf.AreUnited(q[1], q[2]) ? "Yes" : "No");
            }
        }
        Console.WriteLine(string.Join("\n", l));
    }
예제 #12
0
    static void Main()
    {
        var r = new List <int>();
        var h = Read();
        var n = h[0];

        var uf = new UF(n);

        for (int i = 0; i < h[1]; i++)
        {
            var q = Read();
            if (q[0] == 0)
            {
                uf.Unite(q[1], q[2]);
            }
            else
            {
                r.Add(uf.AreUnited(q[1], q[2]) ? 1 : 0);
            }
        }
        Console.WriteLine(string.Join("\n", r));
    }
예제 #13
0
    static void Main()
    {
        var(n, m) = Read2();
        var uf = new UF(n);

        foreach (var r in new int[m].Select(_ => Read()))
        {
            uf.Unite(r[0], r[1]);
        }

        var q = int.Parse(Console.ReadLine());

        Console.WriteLine(string.Join("\n", new int[q].Select(_ => Read()).Select(r => uf.AreUnited(r[0], r[1]) ? "yes" : "no")));
    }
예제 #14
0
    static void Main()
    {
        var h  = Read();
        var n  = h[0];
        var es = new int[h[1]].Select(_ => Read()).ToArray();
        var qs = new int[int.Parse(Console.ReadLine())].Select(_ => Read()).ToArray();

        var map   = Array.ConvertAll(new int[n], _ => new List <int>());
        var map_r = Array.ConvertAll(new int[n], _ => new List <int>());

        foreach (var e in es)
        {
            map[e[0]].Add(e[1]);
            map_r[e[1]].Add(e[0]);
        }

        var uf    = new UF(n);
        var u     = new bool[n];
        var order = new List <int>();

        Action <int> Dfs = null;

        Dfs = v =>
        {
            u[v] = true;
            foreach (var nv in map[v])
            {
                if (u[nv])
                {
                    continue;
                }
                Dfs(nv);
            }
            order.Add(v);
        };
        for (int v = 0; v < n; v++)
        {
            if (!u[v])
            {
                Dfs(v);
            }
        }

        Action <int> Dfs_r = null;

        Dfs_r = v =>
        {
            u[v] = true;
            foreach (var nv in map_r[v])
            {
                if (u[nv])
                {
                    continue;
                }
                uf.Unite(v, nv);
                Dfs_r(nv);
            }
        };
        Array.Clear(u, 0, n);
        order.Reverse();
        foreach (var v in order)
        {
            if (!u[v])
            {
                Dfs_r(v);
            }
        }

        Console.WriteLine(string.Join("\n", qs.Select(v => uf.AreUnited(v[0], v[1]) ? 1 : 0)));
    }
예제 #15
0
    static void Main()
    {
        var(h, w) = Read2();
        // 1-indexed に注意
        var sv = Read2();
        var ev = Read2();
        var s  = GridHelper.ReadEnclosedGrid(ref h, ref w);

        sv = (sv.i + 1, sv.j + 1);
        ev = (ev.i + 1, ev.j + 1);
        GridHelper.EncloseGrid(ref h, ref w, ref s);

        const char Wall  = '#';
        var        idMap = new int[h, w];

        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w; j++)
            {
                idMap[i, j] = i * w + j;
            }
        }

        var uf = new UF(h * w);

        for (int i = 2; i < h - 2; i++)
        {
            for (int j = 2; j < w - 2; j++)
            {
                if (s[i][j] == Wall)
                {
                    continue;
                }

                if (s[i - 1][j] != Wall)
                {
                    uf.Unite(idMap[i, j], idMap[i - 1, j]);
                }
                if (s[i][j - 1] != Wall)
                {
                    uf.Unite(idMap[i, j], idMap[i, j - 1]);
                }
            }
        }

        var es  = new List <(int v1, int v2)>();
        var sv2 = uf.GetRoot(idMap[sv.i, sv.j]);
        var ev2 = uf.GetRoot(idMap[ev.i, ev.j]);

        for (int i = 2; i < h - 2; i++)
        {
            for (int j = 2; j < w - 2; j++)
            {
                if (s[i][j] == Wall)
                {
                    continue;
                }

                var id = idMap[i, j];

                for (int di = -2; di <= 0; di++)
                {
                    for (int dj = -2; dj <= 2; dj++)
                    {
                        if (s[i + di][j + dj] == Wall)
                        {
                            continue;
                        }

                        var did = idMap[i + di, j + dj];
                        if (uf.AreUnited(id, did))
                        {
                            continue;
                        }

                        var(v1, v2) = (uf.GetRoot(id), uf.GetRoot(did));
                        if (v1 > v2)
                        {
                            (v1, v2) = (v2, v1);
                        }
                        es.Add((v1, v2));
                    }
                }
            }
        }

        var r = ShortestPath.Bfs(h * w, es.Distinct().Select(e => new[] { e.v1, e.v2 }).ToArray(), false, sv2, ev2);

        Console.WriteLine(r.IsConnected(ev2) ? r[ev2] : -1);
    }
예제 #16
0
    static void Main()
    {
        var h = Read();
        int n = h[0], m = h[1];
        var rs = new int[m].Select(_ => Read()).Select((x, id) => (id, a: x[0], b: x[1], c: (long)x[2])).ToArray();
        var n2 = Enumerable.Range(0, 20).Select(i => 1 << i).First(x => x >= n - 1);

        var uf         = new UF(n + 1);
        var minEdges   = new List <int>();
        var extraEdges = new int[n2].Select(_ => new List <int>()).ToArray();
        var maxCost    = new long[m];

        foreach (var r in rs.OrderBy(r => r.c))
        {
            if (!uf.AreUnited(r.a, r.b))
            {
                uf.Unite(r.a, r.b);
                minEdges.Add(r.id);
            }
            else
            {
                extraEdges[n2 >> 1].Add(r.id);
            }
        }
        var minCost = minEdges.Sum(id => rs[id].c);

        // 並列二分探索。
        for (int f = n2 >> 1; f > 0; f >>= 1)
        {
            var uf2 = new UF(n + 1);
            for (int i = 0; i < n2; i++)
            {
                // unite する前に判定します。
                if (i % f == 0 && i / f % 2 == 1)
                {
                    foreach (var id in extraEdges[i])
                    {
                        var(_, a, b, _) = rs[id];
                        if (f > 1)
                        {
                            if (uf2.AreUnited(a, b))
                            {
                                extraEdges[i - (f >> 1)].Add(id);
                            }
                            else
                            {
                                extraEdges[i + (f >> 1)].Add(id);
                            }
                        }
                        else
                        {
                            var maxIndex = uf2.AreUnited(a, b) ? i - 1 : i;
                            maxCost[id] = rs[minEdges[maxIndex]].c;
                        }
                    }
                    extraEdges[i].Clear();
                }

                if (i < n - 1)
                {
                    var r = rs[minEdges[i]];
                    uf2.Unite(r.a, r.b);
                }
            }
        }

        Console.WriteLine(string.Join("\n", maxCost.Select((x, id) => x == 0 ? minCost : minCost + rs[id].c - x)));
    }
예제 #17
0
    static int MinCostArborescence(int n, int sv, List <int[]>[] map, UF uf)
    {
        // 入る辺のうち最小のもの。
        var minEdges = new int[n][];

        for (int v = 0; v < n; v++)
        {
            if (v == sv || map[v]?.Any() != true)
            {
                continue;
            }
            var min = map[v].Min(e => e[2]);
            minEdges[v] = map[v].First(e => e[2] == min);
            uf.Unite(v, minEdges[v][0]);
        }

        var rn = Enumerable.Range(0, n).ToArray();

        if (rn.All(v => uf.AreUnited(v, sv)))
        {
            return(minEdges.Sum(e => e?[2] ?? 0));
        }

        // 根と非連結になっているパスのうち、サイクルとなっている部分を縮約します。
        // 0 型と 6 型のいずれか。
        var sum       = 0;
        var u         = new bool[n];
        var reductMap = new int[n];

        for (int v = 0; v < n; v++)
        {
            if (uf.AreUnited(v, sv))
            {
                map[v].Clear();
                sum         += minEdges[v]?[2] ?? 0;
                reductMap[v] = sv;
                continue;
            }
            if (u[v])
            {
                continue;
            }

            var cycle = Array.FindAll(rn, i => uf.AreUnited(v, i));
            foreach (var i in cycle)
            {
                u[i] = true;
            }

            // vc0 に縮約します。
            var vc0 = cycle[0];

            var gs2 = cycle.Where(i => minEdges[i] != null).Select(i => minEdges[i][0]).GroupBy(i => i).Where(g => g.Count() == 2).ToArray();
            if (gs2.Any())
            {
                // 6 型の場合。
                vc0 = gs2[0].Key;
                var path = new List <int> {
                    vc0
                };
                for (var t = vc0; (t = minEdges[t][0]) != vc0;)
                {
                    path.Add(t);
                }
                cycle = path.ToArray();
            }

            var cycleSum = cycle.Sum(i => minEdges[i]?[2] ?? 0);

            foreach (var i in cycle)
            {
                reductMap[i] = vc0;
                map[i].RemoveAll(e => uf.AreUnited(e[0], e[1]));
                if (i == vc0)
                {
                    foreach (var e in map[i])
                    {
                        e[2] += cycleSum - minEdges[i][2];
                    }
                }
                else
                {
                    foreach (var e in map[i])
                    {
                        e[2] += cycleSum - minEdges[i][2];
                        map[vc0].Add(e);
                    }
                    map[i].Clear();
                }
            }
        }

        foreach (var es in map)
        {
            foreach (var e in es)
            {
                e[0] = reductMap[e[0]];
                e[1] = reductMap[e[1]];
            }
        }

        return(MinCostArborescence(n, sv, map, uf) + sum);
    }