ABC 091 C 2D Plane 2N Points
#atcoder #wa 2018-10-08
https://beta.atcoder.jp/contests/abc091/tasks/arc092_a
二部グラフの最大マッチング問題と見做せば瞬殺なのだけれど、400点だし、そんなの使わなくても出来るかなとグダグダやっていたが出来なかった。いい機会なので、Ford-Fulkersonを実装して二部グラフの最大マッチング問題を解いてみた。Ford-Fulkerson自体は意外と簡単だったが、たぶん時間内に実装はできなかったので$ WA扱い。
解説を見ると、うまく貪欲法でできるらしい。
code:java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int[][] red = new intN2;
int[][] blue = new intN2;
for (int i = 0; i < N; i++) for (int j = 0; j < 2; j++) redij = scanner.nextInt();
for (int i = 0; i < N; i++) for (int j = 0; j < 2; j++) blueij = scanner.nextInt();
boolean[][] connectivity = new booleanNN;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (redi0 < bluej0 && redi1 < bluej1) connectivityij = true;
}
}
System.out.println(solveFF(N, N, connectivity));
}
private static int solveFF(int N, int M, boolean[][] connectivity) {
int NN = N + M + 2;
int[][] graph = new intNNNN;
for (int i = 0; i < N; i++) graph0i + 1 = 1;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (connectivityij) graphi + 1j + N + 1 = 1;
for (int j = 0; j < M; j++) graphj + N + 1NN - 1 = 1;
int[][] flow = new FordFulkerson().solve(NN, graph, 0, NN - 1);
int numPairs = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
if (flowi + 1j + N + 1 > 0) numPairs++;
return numPairs;
}
private static class FordFulkerson {
public int[][] solve(int N, int[][] graph, int src, int dst) {
int[][] flow = new intNN;
int[] path = findPath(N, graph, flow, src, dst);
while (path != null) {
int inc = Integer.MAX_VALUE;
int v = dst;
while (v != src) {
int u = pathv;
int cf = graphuv - flowuv;
if (cf < inc) inc = cf;
v = u;
}
v = dst;
while (v != src) {
int u = pathv;
flowuv += inc;
flowvu -= inc;
v = u;
}
path = findPath(N, graph, flow, src, dst);
}
for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (flowij < 0) flowij = 0;
return flow;
}
private int[] findPath(int N, int[][] graph, int[][] flow, int src, int dst) {
Queue<Integer> queue = new LinkedList<>();
int[] path = new intN;
for (int i = 0; i < N; i++) pathi = -1;
pathsrc = src;
queue.add(src);
while (!queue.isEmpty()) {
int from = queue.poll();
if (from == dst) {
return path;
}
for (int to = 0; to < N; to++) {
if (pathto >= 0) continue;
if (graphfromto - flowfromto > 0
|| flowtofrom > 0) {
pathto = from;
queue.add(to);
}
}
}
return null;
}
}
}