結果

問題 No.19 ステージの選択
ユーザー te-shte-sh
提出日時 2020-01-30 01:31:13
言語 D
(dmd 2.107.1)
結果
AC  
実行時間 2 ms / 5,000 ms
コード長 6,847 bytes
コンパイル時間 2,756 ms
コンパイル使用メモリ 176,936 KB
実行使用メモリ 4,384 KB
最終ジャッジ日時 2023-09-04 05:19:25
合計ジャッジ時間 3,781 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 1 ms
4,376 KB
testcase_05 AC 2 ms
4,376 KB
testcase_06 AC 2 ms
4,376 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 AC 1 ms
4,380 KB
testcase_10 AC 2 ms
4,376 KB
testcase_11 AC 1 ms
4,384 KB
testcase_12 AC 1 ms
4,380 KB
testcase_13 AC 2 ms
4,380 KB
testcase_14 AC 2 ms
4,380 KB
testcase_15 AC 2 ms
4,380 KB
testcase_16 AC 2 ms
4,380 KB
testcase_17 AC 2 ms
4,380 KB
testcase_18 AC 2 ms
4,380 KB
testcase_19 AC 2 ms
4,380 KB
testcase_20 AC 1 ms
4,380 KB
testcase_21 AC 2 ms
4,380 KB
testcase_22 AC 2 ms
4,380 KB
testcase_23 AC 2 ms
4,380 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
Main.d(279): Deprecation: function `Main.IO!(makeGlobal, makeGlobal).IO.put!("{floatFormat: \"%.1f\"}", double).put.putA!(c, double).putA` function requires a dual-context, which is deprecated
Main.d-mixin-256(258):        instantiated from here: `putA!(c, double)`
Main.d(25):        instantiated from here: `put!("{floatFormat: \"%.1f\"}", double)`

ソースコード

diff #

// URL: https://yukicoder.me/problems/no/19

import std.algorithm, std.array, std.container, std.math, std.range, std.typecons, std.string;

version(unittest) {} else
void main()
{
  int N; io.getV(N);
  int[] L, S; io.getC(N, L, S); L[] *= 2; --S[];

  auto uf = new UnionFind(N);
  foreach (i, Si; S) uf.unite(cast(int)i, Si);

  auto groups = uf.groups, r = 0;
  foreach (group; uf.groups) {
    auto za = Zaatsu!int(group);
    auto g = Graph(cast(int)group.length);
    foreach (u; group)
      g.addEdge(za.comp(S[u]), za.comp(u));

    auto scc = g.stronglyConnectedComponentsKosaraju.comps;
    r += L.indexed(group).sum/2 + L.indexed(za.uncomp(scc[0])).minElement/2;
  }

  io.put!`{floatFormat: "%.1f"}`(cast(double)r/2);
}

class UnionFind
{
  int n;

  this(int n)
  {
    this.n = this.s = n;
    p = new int[](n); p[] = s;
    cf = n;
    cn = new size_t[](n); cn[] = 1;
  }

  bool unite(int u, int v)
  {
    auto pu = subst(u), pv = subst(v);
    if (pu != pv) {
      p[pv] = pu;
      --cf;
      cn[pu] += cn[pv];
      return true;
    } else {
      return false;
    }
  }

  bool isSame(int u, int v) { return subst(u) == subst(v); }
  size_t countForests() { return cf; }
  size_t countNodes(int u) { return cn[subst(u)]; }

  auto groups()
  {
    auto g = new int[][](n);
    foreach (i; 0..n) g[subst(i)] ~= i;
    return g.filter!(l => !l.empty);
  }

  private
  {
    int[] p;
    int s;
    size_t cf;
    size_t[] cn;

    int subst(int i) { return p[i] == s ? i : (p[i] = subst(p[i])); }
  }
}

struct Zaatsu(T)
{
  const size_t n;

  this(U...)(U v)
  {
    T[] d;
    foreach (w; v) d ~= w.array;
    auto u = d.sort.uniq;
    n = u.walkLength;
    c2 = new T[](n);

    foreach (i, ui; u.enumerate(0)) {
      c1[ui] = i;
      c2[i] = ui;
    }
  }

  int comp(T v) { return c1[v]; }
  auto comp(R)(R v) if (isInputRange!R) { return v.map!(w => c1[w]); }

  T uncomp(int v) { return c2[v]; }
  auto uncomp(R)(R v) if (isInputRange!R) { return v.map!(w => c2[w]); }

  private
  {
    int[T] c1;
    T[] c2;
  }
}

struct Graph
{
  alias Node = int;
  Node n;
  Node[][] g;
  alias g this;
  this(Node n) { this.n = n; g = new Node[][](n); }
  void addEdge(Node u, Node v) { g[u] ~= v; }
  void addEdgeB(Node u, Node v) { g[u] ~= v; g[v] ~= u; }
}

struct GraphW(W = int, W i = 10^^9)
{
  alias Node = int, Wt = W, inf = i;
  struct Edge { Node src, dst; Wt wt; alias cap = wt; }
  Node n;
  Edge[][] g;
  alias g this;
  this(Node n) { this.n = n; g = new Edge[][](n); }
  void addEdge(Node u, Node v, Wt w) { g[u] ~= Edge(u, v, w); }
  void addEdgeB(Node u, Node v, Wt w) { g[u] ~= Edge(u, v, w); g[v] ~= Edge(v, u, w); }
}

struct GraphM(W = int, W i = 10^^9)
{
  alias Node = int, Wt = W, inf = i;
  Node n;
  Wt[][] g;
  alias g this;
  this(int n) { this.n = n; g = new Wt[][](n, n); }
  static GraphM!(W, i) init(Node n)
  {
    auto g = GraphM!(W, i)(n);
    foreach (i; 0..n) { g[i][] = inf; g[i][i] = 0; }
    return g;
  }
}

struct StronglyConnectedComponentsKosaraju(Graph)
{
  alias Node = Graph.Node;
  Graph g;
  alias g this;
  Node[][] comps;

  this(Graph g)
  {
    this.g = g;

    auto rdj = Graph(n), visited = new bool[](n);
    foreach (u; 0..n)
      foreach (v; g[u])
        rdj.addEdge(v, u);

    auto dfs(Node s, Graph adj)
    {
      auto q = SList!Node(s);
      visited[s] = true;
      Node[] comp;
      while (!q.empty) {
        auto u = q.front; q.removeFront();
        foreach (v; adj[u])
          if (!visited[v]) {
            visited[v] = true;
            q.insertFront(v);
          }
        comp ~= u;
      }
      comp.reverse();
      return comp;
    }

    Node[] ord;
    foreach (u; 0..n) if (!visited[u]) ord ~= dfs(u, g);
    visited[] = false;
    foreach_reverse (u; ord) if (!visited[u]) comps ~= dfs(u, rdj);
  }
}
StronglyConnectedComponentsKosaraju!Graph stronglyConnectedComponentsKosaraju(Graph)(Graph g)
{ return StronglyConnectedComponentsKosaraju!Graph(g); }

struct StronglyConnectedComponentsGabow(Graph)
{
  alias Node = Graph.Node;
  Graph g;
  alias g this;
  Node[][] comps;

  this(Graph g)
  {
    this.g = g;
    Node[] i = new Node[](n);
    auto s = SList!Node(), b = SList!Node(), ns = Node(0);

    void dfs(Node u)
    {
      b.insert(i[u] = ns);
      s.insert(u); ++ns;
      foreach (v; g[u]) {
        if (!i[v]) dfs(v);
        else while (i[v] < b.front) b.removeFront;
      }
      if (i[u] == b.front) {
        comps ~= [[]];
        b.removeFront;
        while (i[u] < ns) {
          comps[$-1] ~= s.front;
          i[s.front] = n + cast(Node)comps.length;
          s.removeFront; --ns;
        }
      }
    }

    foreach (u; 0..n) if (!i[u]) dfs(u);
  }
}
StronglyConnectedComponentsGabow!Graph stronglyConnectedComponentsGabow(Graph)(Graph g)
{ return StronglyConnectedComponentsGabow!Graph(g); }

auto io = IO!()();
import std.stdio;
struct IO(alias IN = stdin, alias OUT = stdout)
{
  import std.conv, std.format, std.meta, std.traits;

  auto getV(T...)(ref T v) { foreach (ref w; v) get(w); }
  auto getA(T)(size_t n, ref T v) if (hasAssignableElements!T)
  { v = new T(n); foreach (ref w; v) get(w); }
  auto getC(T...)(size_t n, ref T v)
  if (allSatisfy!(hasAssignableElements, T))
  {
    foreach (ref w; v) w = new typeof(w)(n);
    foreach (i; 0..n) foreach (ref w; v) get(w[i]);
  }
  auto getM(T)(size_t r, size_t c, ref T v)
  if (hasAssignableElements!T && hasAssignableElements!(ElementType!T))
  {
    v = new T(r); foreach (ref w; v) getA(c, w);
  }
  template getS(E...)
  {
    auto getS(T)(size_t n, ref T v)
    {
      v = new T(n); foreach (ref w; v) foreach (e; E) mixin("get(w."~e~");");
    }
  }

  auto put(alias conf = "{}", T...)(T v)
  {
    import core.stdc.stdlib;
    mixin("
    const PutConf c = "~conf~";
    foreach (i, w; v) { putA!c(w); if (i < v.length-1) OUT.write(c.delimiter); }
    static if (c.newline) OUT.writeln;
    static if (c.flush) OUT.flush();
    static if (c.exit) exit(0);
    ");
  }
  auto putB(alias conf = "{}", S, T)(bool c, S t, T f) { if (c) put(t); else put(f); }
  auto putRaw(T...)(T v) { OUT.write(v); OUT.writeln; }

  private
  {
    dchar[] buf;
    auto sp = (new dchar[](0)).splitter;
    void nextLine() { IN.readln(buf); sp = buf.splitter; }
    auto get(T)(ref T v) { if (sp.empty) nextLine(); v = sp.front.to!T; sp.popFront(); }

    auto putR(alias c, T)(T v)
    {
      auto w = v;
      while (!w.empty) { putA!c(w.front); w.popFront(); if (!w.empty) OUT.write(c.delimiter); }
    }
    auto putA(alias c, T)(T v)
    {
      static if (isInputRange!T && !isSomeString!T) putR!c(v);
      else if (isFloatingPoint!T) OUT.write(format(c.floatFormat, v));
      else OUT.write(v);
    }
  }
}
const struct PutConf
{
  bool newline = true;
  bool flush;
  bool exit;
  string floatFormat = "%.10f";
  string delimiter = " ";
}
0