Submission #1148118

#TimeUsernameProblemLanguageResultExecution timeMemory
1148118rebe__1Coin Collecting (JOI19_ho_t4)Java
37 / 100
1092 ms249816 KiB
import java.util.*;

public class joi2019_ho_t4 {

  static class Edge {
    int to, rev, cap, cost;
    public Edge(int to, int rev, int cap, int cost) {
      this.to = to;
      this.rev = rev;
      this.cap = cap;
      this.cost = cost;
    }
  }

  static final int INF = 1000000000;

  ArrayList<Edge>[] graph;
  int N;

  public joi2019_ho_t4(int N) {
    this.N = N;
    graph = new ArrayList[N];
    for (int i = 0; i < N; i++) {
      graph[i] = new ArrayList<>();
    }
  }

  void addEdge(int s, int t, int cap, int cost) {
    graph[s].add(new Edge(t, graph[t].size(), cap, cost));
    graph[t].add(new Edge(s, graph[s].size() - 1, 0, -cost));
  }

  int minCostFlow(int s, int t, int f) {
    int res = 0;
    int[] dist = new int[N];
    int[] prevV = new int[N];
    int[] prevE = new int[N];

    while (f > 0) {
      Arrays.fill(dist, INF);
      dist[s] = 0;
      boolean[] inQueue = new boolean[N];
      Queue<Integer> que = new LinkedList<>();
      que.add(s);
      inQueue[s] = true;
      while (!que.isEmpty()) {
        int u = que.poll();
        inQueue[u] = false;
        for (int i = 0; i < graph[u].size(); i++) {
          Edge e = graph[u].get(i);
          if (e.cap > 0 && dist[e.to] > dist[u] + e.cost) {
            dist[e.to] = dist[u] + e.cost;
            prevV[e.to] = u;
            prevE[e.to] = i;
            if (!inQueue[e.to]) {
              que.add(e.to);
              inQueue[e.to] = true;
            }
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      int d = f;
      for (int v = t; v != s; v = prevV[v]) {
        d = Math.min(d, graph[prevV[v]].get(prevE[v]).cap);
      }
      f -= d;
      res += d * dist[t];
      for (int v = t; v != s; v = prevV[v]) {
        Edge e = graph[prevV[v]].get(prevE[v]);
        e.cap -= d;
        graph[v].get(e.rev).cap += d;
      }
    }
    return res;
  }

  private static int constrain(int value, int min, int max) {
    if (value < min) return min;
    if (value > max) return max;
    return value;
  }

  private static long calculateMovesToBoundary(int col, int row, int numColumns) {
    long moves = 0;
    if (row < 1) moves += (1 - row);
    if (row > 2) moves += (row - 2);
    if (col < 1) moves += (1 - col);
    if (col > numColumns) moves += (col - numColumns);
    return moves;
  }

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int numColumns = sc.nextInt();
    int totalCoins = 2 * numColumns;
    int[][] grid = new int[3][numColumns + 1];
    long boundaryCost = 0;

    for (int i = 0; i < totalCoins; i++) {
      int col = sc.nextInt();
      int row = sc.nextInt();
      boundaryCost += calculateMovesToBoundary(col, row, numColumns);
      int validCol = constrain(col, 1, numColumns);
      int validRow = constrain(row, 1, 2);
      grid[validRow][validCol]++;
    }

    int nodes = 2 * numColumns;
    int[] supply = new int[nodes];
    for (int c = 1; c <= numColumns; c++) {
      for (int r = 1; r <= 2; r++) {
        int idx = (c - 1) * 2 + (r - 1);
        supply[idx] = grid[r][c] - 1;
      }
    }

    int s = nodes;
    int t = nodes + 1;
    int totalNodes = nodes + 2;
    joi2019_ho_t4 mcf = new joi2019_ho_t4(totalNodes);

    for (int c = 1; c < numColumns; c++) {
      for (int r = 1; r <= 2; r++) {
        int u = (c - 1) * 2 + (r - 1);
        int v = (c) * 2 + (r - 1);
        mcf.addEdge(u, v, INF, 1);
        mcf.addEdge(v, u, INF, 1);
      }
    }

    for (int c = 1; c <= numColumns; c++) {
      int u = (c - 1) * 2 + 0;
      int v = (c - 1) * 2 + 1;
      mcf.addEdge(u, v, INF, 1);
      mcf.addEdge(v, u, INF, 1);
    }

    int totalPositive = 0;
    for (int i = 0; i < nodes; i++) {
      if (supply[i] > 0) {
        mcf.addEdge(s, i, supply[i], 0);
        totalPositive += supply[i];
      } else if (supply[i] < 0) {
        mcf.addEdge(i, t, -supply[i], 0);
      }
    }

    int flowCost = mcf.minCostFlow(s, t, totalPositive);

    long answer = boundaryCost + flowCost;
    System.out.println(answer);
  }
}

Compilation message (stderr)

Note: joi2019_ho_t4.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

=======
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...