結果

問題 No.654 Air E869120
ユーザー 明智重蔵明智重蔵
提出日時 2022-06-26 21:28:41
言語 C#
(.NET 8.0.203)
結果
WA  
実行時間 -
コード長 9,538 bytes
コンパイル時間 10,457 ms
コンパイル使用メモリ 167,620 KB
実行使用メモリ 190,608 KB
最終ジャッジ日時 2024-11-17 11:17:53
合計ジャッジ時間 21,315 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 73 ms
31,616 KB
testcase_01 WA -
testcase_02 AC 72 ms
31,616 KB
testcase_03 AC 72 ms
31,616 KB
testcase_04 AC 73 ms
31,488 KB
testcase_05 AC 73 ms
31,616 KB
testcase_06 AC 72 ms
31,600 KB
testcase_07 AC 73 ms
31,616 KB
testcase_08 AC 72 ms
31,616 KB
testcase_09 AC 72 ms
31,488 KB
testcase_10 WA -
testcase_11 WA -
testcase_12 AC 538 ms
60,544 KB
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 RE -
testcase_34 RE -
testcase_35 AC 72 ms
31,356 KB
testcase_36 AC 72 ms
31,616 KB
testcase_37 AC 72 ms
31,460 KB
testcase_38 AC 72 ms
31,460 KB
testcase_39 AC 72 ms
190,608 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
  復元対象のプロジェクトを決定しています...
  /home/judge/data/code/main.csproj を復元しました (97 ms)。
MSBuild のバージョン 17.9.6+a4ecab324 (.NET)
  main -> /home/judge/data/code/bin/Release/net8.0/main.dll
  main -> /home/judge/data/code/bin/Release/net8.0/publish/

ソースコード

diff #

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

// https://yukicoder.me/problems/no/654
class Program
{
    static string InputPattern = "InputX";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("2 2 5");
            WillReturn.Add("1 2 0 25 10");
            WillReturn.Add("1 2 10 40 5");
            //15
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("4 5 5");
            WillReturn.Add("1 2 0 15 40");
            WillReturn.Add("1 3 5 20 10");
            WillReturn.Add("2 3 30 40 20");
            WillReturn.Add("2 4 50 80 20");
            WillReturn.Add("3 4 50 70 30");
            //50
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("3 4 5");
            WillReturn.Add("1 2 0 10 10");
            WillReturn.Add("1 2 10 20 3");
            WillReturn.Add("2 3 15 25 2");
            WillReturn.Add("2 3 5 15 10");
            //2
        }
        else if (InputPattern == "Input4") {
            WillReturn.Add("4 3 5");
            WillReturn.Add("1 2 0 10 100");
            WillReturn.Add("2 3 15 31 100");
            WillReturn.Add("3 4 35 45 100");
            //0
        }
        else if (InputPattern == "Input5") {
            WillReturn.Add("4 40 9");
            WillReturn.Add("2 3 90 99 43");
            WillReturn.Add("2 3 12 60 56");
            WillReturn.Add("1 3 5 9 30");
            WillReturn.Add("4 3 76 96 88");
            WillReturn.Add("2 4 76 86 66");
            WillReturn.Add("1 2 36 91 5");
            WillReturn.Add("2 1 23 82 87");
            WillReturn.Add("1 4 66 83 12");
            WillReturn.Add("1 2 2 33 72");
            WillReturn.Add("4 1 2 90 30");
            WillReturn.Add("3 2 32 84 25");
            WillReturn.Add("4 2 13 99 56");
            WillReturn.Add("4 3 49 56 94");
            WillReturn.Add("1 3 29 42 31");
            WillReturn.Add("1 2 86 88 93");
            WillReturn.Add("3 4 43 51 28");
            WillReturn.Add("3 4 5 69 60");
            WillReturn.Add("3 1 3 4 39");
            WillReturn.Add("1 4 7 73 99");
            WillReturn.Add("3 2 31 85 94");
            WillReturn.Add("1 2 89 94 94");
            WillReturn.Add("2 1 34 70 62");
            WillReturn.Add("3 4 39 94 63");
            WillReturn.Add("4 1 23 30 96");
            WillReturn.Add("3 4 41 81 29");
            WillReturn.Add("4 3 57 62 48");
            WillReturn.Add("3 2 33 54 27");
            WillReturn.Add("3 1 44 73 44");
            WillReturn.Add("3 2 50 70 19");
            WillReturn.Add("4 2 19 36 82");
            WillReturn.Add("4 2 95 97 94");
            WillReturn.Add("3 4 20 58 10");
            WillReturn.Add("1 4 4 97 33");
            WillReturn.Add("2 3 46 58 58");
            WillReturn.Add("3 1 0 80 45");
            WillReturn.Add("4 1 1 76 43");
            WillReturn.Add("3 2 16 97 9");
            WillReturn.Add("3 1 13 16 45");
            WillReturn.Add("2 4 4 16 12");
            WillReturn.Add("2 3 68 98 12");
            //240
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static int mN;
    static int mD;

    static int mSourceNode;
    static int mSinkNode;
    static int UB;

    // 隣接行列で枝を表現
    static int[,] mCapacityArr;
    static int[,] mFlowArr;

    struct PlaneInfoDef
    {
        internal int StaNode;
        internal int EndNode;
        internal int StaTime;
        internal int EndTime;
        internal int Capacity;
    }
    static List<PlaneInfoDef> mPlaneInfoList = new List<PlaneInfoDef>();

    static void Main()
    {
        List<string> InputList = GetInputList();

        int[] wkArr = { };
        Action<string> SplitAct = pStr =>
            wkArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();

        SplitAct(InputList[0]);
        mN = wkArr[0];
        mD = wkArr[2];

        foreach (string EachStr in InputList.Skip(1)) {
            SplitAct(EachStr);
            PlaneInfoDef WillAdd;
            WillAdd.StaNode = wkArr[0];
            WillAdd.EndNode = wkArr[1];
            WillAdd.StaTime = wkArr[2];
            WillAdd.EndTime = wkArr[3];
            WillAdd.Capacity = wkArr[4];

            // ゴールノードでない場合は、乗り換え時間を足す
            if (WillAdd.EndNode != mN) {
                WillAdd.EndTime += mD;
            }

            mPlaneInfoList.Add(WillAdd);
        }

        // 出発時間の昇順にソートしておく
        mPlaneInfoList = mPlaneInfoList.OrderBy(pX => pX.StaTime).ToList();

        //for (int I = 0; I <= mPlaneInfoList.Count - 1; I++) {
        //    Console.WriteLine("NodeID={0},StaNode={1},EndNode={2},StaTime={3},EndTime={4},Capacity={5}",
        //        I,
        //        mPlaneInfoList[I].StaNode, mPlaneInfoList[I].EndNode,
        //        mPlaneInfoList[I].StaTime, mPlaneInfoList[I].EndTime,
        //        mPlaneInfoList[I].Capacity);
        //}

        mSourceNode = mPlaneInfoList.Count;
        mSinkNode = mSourceNode + 1;
        UB = mSinkNode;

        mCapacityArr = new int[UB + 1, UB + 1];
        mFlowArr = new int[UB + 1, UB + 1];

        // グラフに枝を追加する
        for (int I = 0; I <= mPlaneInfoList.Count - 1; I++) {
            for (int J = 0; J <= mPlaneInfoList.Count - 1; J++) {
                if (mPlaneInfoList[I].EndNode == mPlaneInfoList[J].StaNode) {
                    if (mPlaneInfoList[I].EndTime <= mPlaneInfoList[J].StaTime) {
                        mCapacityArr[I, J] = mPlaneInfoList[I].Capacity;
                        break;
                    }
                }
            }
        }
        int CapacitySum = mPlaneInfoList.Sum(pX => pX.Capacity);

        // 空港で待つ分の枝
        for (int I = 0; I <= mPlaneInfoList.Count - 1; I++) {
            for (int J = 0; J <= mPlaneInfoList.Count - 1; J++) {
                if (I == J) continue;
                if (mPlaneInfoList[I].StaNode == mPlaneInfoList[J].StaNode) {
                    if (mPlaneInfoList[I].StaTime <= mPlaneInfoList[J].StaTime) {
                        mCapacityArr[I, J] = int.MaxValue;
                    }
                }
            }
        }

        for (int I = 0; I <= mPlaneInfoList.Count - 1; I++) {
            if (mPlaneInfoList[I].StaNode == 1) {
                mCapacityArr[mSourceNode, I] = CapacitySum;
            }
        }
        for (int I = 0; I <= mPlaneInfoList.Count - 1; I++) {
            if (mPlaneInfoList[I].EndNode == mN) {
                mCapacityArr[I, mSinkNode] = mPlaneInfoList[I].Capacity;
            }
        }

        // エドモンズ・カープで解く
        Solve();
    }

    static void Solve()
    {
        while (true) {
            List<int> NodeList = ExecBFS();
            if (NodeList == null) break;

            //Console.WriteLine("経路を発見しました");
            //NodeList.ForEach(pX => Console.Write("{0},", pX));
            //Console.WriteLine();

            // 経路に流す量
            int CurrFlow = int.MaxValue;

            for (int I = 0; I <= NodeList.Count - 2; I++) {
                int FromNode = NodeList[I];
                int ToNode = NodeList[I + 1];

                CurrFlow = Math.Min(CurrFlow, mCapacityArr[FromNode, ToNode]);
            }
            //Console.WriteLine("この経路に{0}の水を流します", CurrFlow);

            for (int I = 0; I <= NodeList.Count - 2; I++) {
                int FromNode = NodeList[I];
                int ToNode = NodeList[I + 1];

                mCapacityArr[FromNode, ToNode] -= CurrFlow;
                mFlowArr[FromNode, ToNode] += CurrFlow;

                // 逆辺を追加する
                mCapacityArr[ToNode, FromNode] += CurrFlow;
            }
        }

        int Answer = 0;
        for (int I = 0; I <= UB; I++) {
            Answer += mFlowArr[I, UB];
        }
        Console.WriteLine(Answer);
    }

    struct JyoutaiDef
    {
        internal int CurrNode;
        internal List<int> NodeList;
    }

    // 幅優先探索を行い、始点から終点へのノードのListを返す
    // なければnullを返す
    static List<int> ExecBFS()
    {
        var Queue = new Queue<JyoutaiDef>();
        JyoutaiDef WillEnqueue;
        WillEnqueue.CurrNode = mSourceNode; // 始点のノードはmSourceNode
        WillEnqueue.NodeList = new List<int>();
        WillEnqueue.NodeList.Add(WillEnqueue.CurrNode);
        Queue.Enqueue(WillEnqueue);

        // BFSを繰り返すので、レベルの低い訪問を優先しても問題ない
        var VisitedSet = new HashSet<int>();

        while (Queue.Count > 0) {
            JyoutaiDef Dequeued = Queue.Dequeue();

            // 終点のノードはmSinkNode
            if (Dequeued.CurrNode == mSinkNode) {
                return Dequeued.NodeList;
            }

            for (int I = 0; I <= UB; I++) {
                int CurrCapacity = mCapacityArr[Dequeued.CurrNode, I];
                if (CurrCapacity == 0) continue;

                if (VisitedSet.Add(I) == false) continue;

                WillEnqueue.CurrNode = I;
                WillEnqueue.NodeList = new List<int>(Dequeued.NodeList) { I };
                Queue.Enqueue(WillEnqueue);
            }
        }
        return null;
    }
}
0