Submission #230913


Source Code Expand

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;

class Myon
{
    public Myon() { }
    public static int Main()
    {
        new Myon().calc();
        return 0;
    }


    int N;
    int[] x, y;

    List<int>[] es;
    int[] parent;
    int[,] dp;
    int[] depth;

    int MAX = 20;

    void calc()
    {
        Scanner cin = new Scanner();
        N = cin.nextInt();
        x = new int[N];
        y = new int[N];

        for (int i = 0; i < N - 1; i++)
        {
            x[i] = cin.nextInt() - 1;
            y[i] = cin.nextInt() - 1;
        }

        //辺を全てリストに入れる
        es = new List<int>[N];
        for (int i = 0; i < N; i++)
        {
            es[i] = new List<int>();
        }

        for (int i = 0; i < N; i++)
        {
            es[x[i]].Add(y[i]);
            es[y[i]].Add(x[i]);
        }

        //親、1,2,4,8...個上、自分の深さの情報を
        //dfsで求める
        parent = new int[N];
        dp = new int[N, MAX];
        depth = new int[N];

        dfs(0, -1, 0);

        //ここからクエリごとの処理
        int Q = cin.nextInt();
        for (int i = 0; i < Q; i++)
        {
            int a = cin.nextInt() - 1;
            int b = cin.nextInt() - 1;

            //高さを揃える
            int ret = 0;
            if (depth[a] > depth[b])
            {
                swap(ref a, ref b);
            }
            if (depth[a] < depth[b])
            {
                ret = depth[b] - depth[a];
                b = getV(b, ret);
            }

            //一致しないぎりぎりのところまで登って行く
            //16, 8, 4, 2, 1個上・・・・って順番で見ていけば
            //一致しないぎりぎりのところが求められる
            for (int j = MAX - 1; j >= 0; j--)
            {
                if (dp[a, j] == dp[b, j]) continue;
                else
                {
                    a = dp[a, j];
                    b = dp[b, j];
                    ret += 2 * (1 << j);
                }
            }
            //高さを揃えた時点で、一致しているケースは
            //すでに一致しているので足す必要はないが、
            //一致していないケースは、それぞれ1個上る必要がある
            //そこで、ret に2を足してあげる
            if (a != b) ret += 2;

            //最後に、追加される1つの辺が閉路に加わるので
            //1を足してあげる
            ret += 1;
            Console.WriteLine(ret);
        }
    }

    //swap
    void swap<T>(ref T a, ref T b)
    {
        T c = a;
        a = b;
        b = c;
    } 

    int getV(int a, int dep)
    {
        int now = a;

        //頂点aのdep個上の値を得る
        for (int i = 0; (1 << i) <= dep; i++)
        {
            if ((dep >> i) % 2 == 1)
            {
                now = dp[now, i];
                //dp[a, b] っていうのは、aの2^b個上を見れる。
            }
        }
        return now;
    }

    void dfs(int a, int pre, int dep)
    {
        depth[a] = dep;
        parent[a] = pre;
        dp[a, 0] = pre;

        //ダブリングを用いて、1,2,4,8個上を決めていく
        for (int i = 1; i < MAX; i++)
        {
            if (dp[a, i - 1] != -1) dp[a, i] = dp[dp[a, i - 1], i - 1];
            else dp[a, i] = -1;
        }

        //次の頂点を探す
        foreach (var item in es[a])
        {
            if (item == pre) continue;
            dfs(item, a, dep + 1);
        }
    }

}




class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        do
        {
            s = Console.ReadLine().Split(cs, StringSplitOptions.RemoveEmptyEntries);
        } while ((s.Length == 1 && s[0] == "") || s.Length == 0);
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}

Submission Info

Submission Time
Task D - 閉路
User chokudai
Language C# (Mono 2.10.8.1)
Score 100
Code Size 4536 Byte
Status AC
Exec Time 1533 ms
Memory 55264 KB

Judge Result

Set Name Sample Subtask1 Subtask2
Score / Max Score 0 / 0 30 / 30 70 / 70
Status
AC × 3
AC × 12
AC × 27
Set Name Test Cases
Sample subtask0_sample01.txt, subtask0_sample02.txt, subtask0_sample03.txt
Subtask1 subtask1_01.txt, subtask1_02.txt, subtask1_03.txt, subtask1_04.txt, subtask1_05.txt, subtask1_06.txt, subtask1_07.txt, subtask1_08.txt, subtask1_09.txt, subtask1_10.txt, subtask1_11.txt, subtask1_12.txt
Subtask2 subtask0_sample01.txt, subtask0_sample02.txt, subtask0_sample03.txt, subtask1_01.txt, subtask1_02.txt, subtask1_03.txt, subtask1_04.txt, subtask1_05.txt, subtask1_06.txt, subtask1_07.txt, subtask1_08.txt, subtask1_09.txt, subtask1_10.txt, subtask1_11.txt, subtask1_12.txt, subtask2_01.txt, subtask2_02.txt, subtask2_03.txt, subtask2_04.txt, subtask2_05.txt, subtask2_06.txt, subtask2_07.txt, subtask2_08.txt, subtask2_09.txt, subtask2_10.txt, subtask2_11.txt, subtask2_12.txt
Case Name Status Exec Time Memory
subtask0_sample01.txt AC 115 ms 7836 KB
subtask0_sample02.txt AC 107 ms 7864 KB
subtask0_sample03.txt AC 108 ms 7768 KB
subtask1_01.txt AC 437 ms 40088 KB
subtask1_02.txt AC 430 ms 40112 KB
subtask1_03.txt AC 110 ms 7780 KB
subtask1_04.txt AC 109 ms 7832 KB
subtask1_05.txt AC 118 ms 8056 KB
subtask1_06.txt AC 113 ms 8092 KB
subtask1_07.txt AC 453 ms 26256 KB
subtask1_08.txt AC 468 ms 26216 KB
subtask1_09.txt AC 471 ms 26216 KB
subtask1_10.txt AC 463 ms 26204 KB
subtask1_11.txt AC 452 ms 26220 KB
subtask1_12.txt AC 476 ms 26220 KB
subtask2_01.txt AC 1297 ms 55264 KB
subtask2_02.txt AC 1405 ms 55260 KB
subtask2_03.txt AC 927 ms 8028 KB
subtask2_04.txt AC 1000 ms 8040 KB
subtask2_05.txt AC 963 ms 8424 KB
subtask2_06.txt AC 940 ms 8420 KB
subtask2_07.txt AC 1483 ms 41200 KB
subtask2_08.txt AC 1424 ms 41192 KB
subtask2_09.txt AC 1456 ms 41188 KB
subtask2_10.txt AC 1414 ms 41252 KB
subtask2_11.txt AC 1533 ms 41324 KB
subtask2_12.txt AC 1442 ms 41316 KB