挑战程序竞赛系列(27):3.5二分图匹配(2)
来源:互联网 发布:淘宝小号 浮云网 编辑:程序博客网 时间:2024/06/17 15:27
挑战程序竞赛系列(27):3.5二分图匹配(2)
详细代码可以fork下Github上leetcode项目,不定期更新。
练习题如下:
- POJ 1466: Girls and Boys
- POJ 3692: Kindergarten
- POJ 2724: Purifying Machine
- POJ 2226: Muddy Fields
- POJ 2251: Merry Christmas
POJ 1466: Girls and Boys
活生生的拆散情侣啊,求最大匹配数,接着一刀切,所以答案就是所有学生数减去最大匹配数,当然需要注意addEdge方法,只需要添加一条边即可。因为题目假设情侣们都是两情相悦滴。
代码如下:
import java.io.InputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Scanner;public class Main{ InputStream is; PrintWriter out; String INPUT = "./data/judge/201707/1466.txt"; void solve() { while (in.hasNext()){ int n = in.nextInt(); init(n); for (int i = 0; i < n; ++i){ in.next(); String str = in.next(); int num = Integer.parseInt(str.substring(1, str.length() - 1)); for (int j = 0; j < num; ++j){ int id = in.nextInt(); addEdge(i, id); } } int pairs = bipartiteMatching(); System.out.println(n - pairs); } in.close(); } //二分图 List<Integer>[] g; int[] matching; int V; public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; } Scanner in; public Main(){ in = new Scanner(System.in); } void run() throws Exception { solve(); } public static void main(String[] args) throws Exception { new Main().run(); }}
当然你也可以参考《挑战》P221关于匹配,边覆盖,独立集和顶点覆盖的概念和公式,简单说说。
上述概念都针对一般图,于是有:
(a) 对于不存在孤立点的图,|最大匹配| + |最小边覆盖| = |V|
(b) |最大独立集| + |最小顶点覆盖| = |V|
问题a,求出最大匹配即能求出最小边覆盖,问题b中,针对一般图,求解最大独立集和最小顶点覆盖是NP困难的,但是在二分图中有:
(c) |最大匹配| = |最小顶点覆盖|
所以二分图中能够快速求出最大独立集。
POJ 3692: Kindergarten
思路:可以转换为求补图的最大独立集,而补图恰好是个二分图。二分图的最大独立集 = 总点数 - 二分图最大匹配。于是问题就转换成了求补图的最大匹配了。
证明:补图中的最大独立集,彼此没有边相连,反过来就是彼此都互相连接。
代码如下:
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.InputMismatchException;import java.util.List;public class Main{ InputStream is; PrintWriter out; String INPUT = "./data/judge/201707/3692.txt"; void solve() { int cnt = 0; while (true){ int G = ni(); int B = ni(); int M = ni(); if (G + B + M == 0) break; init(G + B); boolean[][] gg = new boolean[G][B]; for (int i = 0; i < M; ++i){ int g = ni(); int b = ni(); g --; b --; gg[g][b] = true; } for (int i = 0; i < G; ++i){ for (int j = 0; j < B; ++j){ if (!gg[i][j]) addEdge(i, j + G); } } out.println("Case " + (++cnt) + ": " + (G + B - bipartiteMatching())); } } //二分图 List<Integer>[] g; int V; int[] matching; public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); g[to].add(from); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; } void run() throws Exception { is = oj ? System.in : new FileInputStream(new File(INPUT)); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); tr(System.currentTimeMillis() - s + "ms"); } public static void main(String[] args) throws Exception { new Main().run(); } private byte[] inbuf = new byte[1024]; public int lenbuf = 0, ptrbuf = 0; private int readByte() { if (lenbuf == -1) throw new InputMismatchException(); if (ptrbuf >= lenbuf) { ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if (lenbuf <= 0) return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while ((b = readByte()) != -1 && isSpaceChar(b)) ; return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char) skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' // ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while (p < n && !(isSpaceChar(b))) { buf[p++] = (char) b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for (int i = 0; i < n; i++) map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private boolean oj = System.getProperty("ONLINE_JUDGE") != null; private void tr(Object... o) { if (!oj) System.out.println(Arrays.deepToString(o)); }}
POJ 2724: Purifying Machine
题意可参考博文:http://www.hankcs.com/program/algorithm/poj-2724-purifying-machine.html
这台净化机是可以编程的,意味着:
3 3*011000110 0会有:101,001,100,011编程:10* (101, 100)合并而成0*1 (001, 011)合并而成所以最少操作为2次
那么无非就是尽可能的多构造*
,首先把含*
的构造成0or1,接着编辑距离为1的两个num建立连接,因为它们可能构成新的*
,从而降低操作次数,二分图匹配求最大独立集。
代码如下:
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.InputMismatchException;import java.util.List;import java.util.Set;public class Main{ InputStream is; PrintWriter out; String INPUT = "./data/judge/201707/2724.txt"; void solve() { while (true){ int N = ni(); int M = ni(); if (N + M == 0) break; Set<Integer> set = new HashSet<Integer>(); for (int i = 0; i < M; ++i){ String line = ns(); if (line.contains("*")){ int a1 = 0; int a2 = 0; for (char c : line.toCharArray()){ if (c != '*'){ a1 |= c - '0'; a2 |= c - '0'; } else{ a1 |= 0; a2 |= 1; } a1 <<= 1; a2 <<= 1; } set.add(a1 >> 1); set.add(a2 >> 1); } else{ int num = 0; for (char c : line.toCharArray()){ num |= c - '0'; num <<= 1; } set.add(num >> 1); } } Set<Integer> dict = new HashSet<Integer>(); for (int i = 0, num = 1; i < N; ++i){ dict.add(num); num <<= 1; } List<Integer> operations = new ArrayList<Integer>(set); init(set.size()); for (int i = 0; i < V; ++i){ for (int j = i + 1; j < V; ++j){ int diff = operations.get(i) ^ operations.get(j); if (dict.contains(diff)){ addEdge(i, j); } } } out.println(V - bipartiteMatching()); } } //二分图 List<Integer>[] g; int V; int[] matching; public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); g[to].add(from); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; } void run() throws Exception { is = oj ? System.in : new FileInputStream(new File(INPUT)); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); tr(System.currentTimeMillis() - s + "ms"); } public static void main(String[] args) throws Exception { new Main().run(); } private byte[] inbuf = new byte[1024]; public int lenbuf = 0, ptrbuf = 0; private int readByte() { if (lenbuf == -1) throw new InputMismatchException(); if (ptrbuf >= lenbuf) { ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if (lenbuf <= 0) return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while ((b = readByte()) != -1 && isSpaceChar(b)) ; return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char) skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' // ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while (p < n && !(isSpaceChar(b))) { buf[p++] = (char) b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for (int i = 0; i < n; i++) map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private boolean oj = System.getProperty("ONLINE_JUDGE") != null; private void tr(Object... o) { if (!oj) System.out.println(Arrays.deepToString(o)); }}
关于位的操作还不够完美,继续优化。
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.InputMismatchException;import java.util.List;import java.util.Set;public class Main{ InputStream is; PrintWriter out; String INPUT = "./data/judge/201707/2724.txt"; void solve() { while (true){ int N = ni(); int M = ni(); if (N + M == 0) break; Set<Integer> set = new HashSet<Integer>(); for (int i = 0; i < M; ++i){ String line = ns(); if (line.contains("*")){ int a1 = 0; int a2 = 0; for (char c : line.toCharArray()){ a1 <<= 1; a2 <<= 1; if (c != '*'){ a1 |= c - '0'; a2 |= c - '0'; } else{ a1 |= 0; a2 |= 1; } } set.add(a1); set.add(a2); } else{ int num = 0; for (char c : line.toCharArray()){ num <<= 1; num |= c - '0'; } set.add(num); } } List<Integer> operations = new ArrayList<Integer>(set); init(set.size()); for (int i = 0; i < V; ++i){ for (int j = i + 1; j < V; ++j){ int diff = operations.get(i) ^ operations.get(j); if ((diff & (-diff)) == diff){ addEdge(i, j); } } } out.println(V - bipartiteMatching()); } } //二分图 List<Integer>[] g; int V; int[] matching; public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); g[to].add(from); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; } void run() throws Exception { is = oj ? System.in : new FileInputStream(new File(INPUT)); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); tr(System.currentTimeMillis() - s + "ms"); } public static void main(String[] args) throws Exception { new Main().run(); } private byte[] inbuf = new byte[1024]; public int lenbuf = 0, ptrbuf = 0; private int readByte() { if (lenbuf == -1) throw new InputMismatchException(); if (ptrbuf >= lenbuf) { ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if (lenbuf <= 0) return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while ((b = readByte()) != -1 && isSpaceChar(b)) ; return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char) skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' // ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while (p < n && !(isSpaceChar(b))) { buf[p++] = (char) b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for (int i = 0; i < n; i++) map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private boolean oj = System.getProperty("ONLINE_JUDGE") != null; private void tr(Object... o) { if (!oj) System.out.println(Arrays.deepToString(o)); }}
对于非零的整数,x & (-x)的值就是将其最低位的1独立出来后的值。具体可以参考《挑战》P157.
POJ 2226: Muddy Fields
思路:二分图最小顶点集等于最大匹配数。此二分匹配一定能覆盖所有沼泽,且一个很重要的条件是宽度为1任意长的木板,所以只需要找做左顶点和上顶点构成的木板即可,接着就是问题转换了。
最少木板数,可以理解为被覆盖的沼泽最少,尽可能不去覆盖这样木板数一定是最少的,可现实总是很残酷,总有那么一些沼泽要披上两层木板,此时拿个木钉把横竖木板钉在一块,所使用的钉子最少,就是所求答案。
代码如下:
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Arrays;import java.util.InputMismatchException;import java.util.List;public class Main{ InputStream is; PrintWriter out; String INPUT = "./data/judge/201707/2226.txt"; void solve() { int R = ni(); int C = ni(); char[][] board = new char[R][C]; for (int i = 0; i < R; ++i){ for (int j = 0; j < C; ++j){ board[i][j] = nc(); } } init(5000 + 16); for (int i = 0; i < R; ++i){ for (int j = 0; j < C; ++j){ if (board[i][j] == '*'){ int x = i, y = j; while (x > 0 && board[x - 1][j] == '*') x--; while (y > 0 && board[i][y - 1] == '*') y--; addEdge(x * 50 + j, i * 50 + y + 2500); } } } out.println(bipartiteMatching()); } //二分图最大匹配等价于最小顶点覆盖 List<Integer>[] g; int V; int[] matching; public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); g[to].add(from); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; } void run() throws Exception { is = oj ? System.in : new FileInputStream(new File(INPUT)); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); tr(System.currentTimeMillis() - s + "ms"); } public static void main(String[] args) throws Exception { new Main().run(); } private byte[] inbuf = new byte[1024]; public int lenbuf = 0, ptrbuf = 0; private int readByte() { if (lenbuf == -1) throw new InputMismatchException(); if (ptrbuf >= lenbuf) { ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if (lenbuf <= 0) return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while ((b = readByte()) != -1 && isSpaceChar(b)) ; return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char) skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while (!(isSpaceChar(b))) { // when nextLine, (isSpaceChar(b) && b != ' // ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while (p < n && !(isSpaceChar(b))) { buf[p++] = (char) b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for (int i = 0; i < n; i++) map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for (int i = 0; i < n; i++) a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ; if (b == '-') { minus = true; b = readByte(); } while (true) { if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } b = readByte(); } } private boolean oj = System.getProperty("ONLINE_JUDGE") != null; private void tr(Object... o) { if (!oj) System.out.println(Arrays.deepToString(o)); }}
在构图时,遍历当前board是否为”*”,接着把它们定位到最上端和最左端的两块木板,并建立边,形成二分图。
POJ 2251: Merry Christmas
思路:假设L个地方需要L个圣诞老人,那么现在就在此基础上尽可能多的节约圣诞老人。所以说假如知道某个地点的圣诞老人出现的时刻,那么在规定时间内能够抵达另一个地方,那么可以省去一个圣诞老人。最多可以省去多少呢?为最大匹配数,这样此题就转换成了二分图的求解。
代码如下:
static final int INF = 1 << 28; void solve() { int[][] distance = new int[100][100]; while (true){ int N = ni(); int M = ni(); int L = ni(); if(N == 0 && M == 0 && L == 0) break; for (int i = 0; i < 100; ++i){ Arrays.fill(distance[i], INF); } for (int i = 0; i < M; ++i){ int from = ni(); int to = ni(); int dis = ni(); distance[from][to] = dis; distance[to][from] = dis; } for (int k = 0; k < N; ++k){ distance[k][k] = 0; for (int i = 0; i < N; ++i){ for (int j = 0; j < N; ++j){ distance[i][j] = Math.min(distance[i][j], distance[i][k] + distance[k][j]); } } } int[] p = new int[L]; int[] t = new int[L]; for (int i = 0; i < L; ++i){ p[i] = ni(); t[i] = ni(); } init(2 * L); for (int i = 0; i < L; ++i){ for (int j = 0; j < L; ++j){ if (i != j && t[i] + distance[p[i]][p[j]] <= t[j]){ addEdge(2 * i, 2 * j + 1); } } } out.println(L - bipartiteMatching()); } } List<Integer>[] g; int V; int[] matching; @SuppressWarnings("unchecked") public void init(int n){ V = n; g = new ArrayList[V]; for (int i = 0; i < V; ++i) g[i] = new ArrayList<Integer>(); matching = new int[V]; } public void addEdge(int from, int to){ g[from].add(to); g[to].add(from); } public boolean dfs(int v, boolean[] visited){ visited[v] = true; for (int u : g[v]){ int w = matching[u]; if (w == -1 || !visited[w] && dfs(w, visited)){ matching[u] = v; matching[v] = u; return true; } } return false; } public int bipartiteMatching(){ int res = 0; Arrays.fill(matching, -1); for (int i = 0; i < V; ++i){ if (matching[i] < 0){ if (dfs(i, new boolean[V])){ res ++; } } } return res; }
很奇怪在全数据集上得到的结果都正确,但在AOJ上跑就Runtime Error,有点气人,欢迎找错。
正确AC代码参考:http://www.hankcs.com/program/algorithm/aoj-2251-merry-christmas.html
- 挑战程序竞赛系列(27):3.5二分图匹配(2)
- 挑战程序竞赛系列(26):3.5二分图匹配(1)
- 挑战程序竞赛系列(67):4.7字符串匹配(2)
- 挑战程序竞赛系列(28):3.5最小费用流
- 挑战程序竞赛系列(82):4.3 LCA(2)
- 挑战程序竞赛系列(66):4.7字符串匹配(1)
- 挑战程序竞赛系列(68):4.7字符串匹配(3)
- 二分图(挑战程序设计竞赛)
- 二分图判定 (挑战程序设计竞赛)
- 挑战程序竞赛系列(25):3.5最大权闭合图
- 挑战程序竞赛系列(81):4.3 LCA(1)
- 挑战程序竞赛系列(1):2.3动态规划
- 挑战程序竞赛系列(4):2.1深度优先搜索
- 挑战程序竞赛系列(5):2.1广度优先搜索
- 挑战程序竞赛系列(6):2.1穷尽搜索
- 挑战程序竞赛系列(9):2.4优先队列
- 挑战程序竞赛系列(10):2.4并查集
- 挑战程序竞赛系列(11):2.5最短路径
- c++构造函数成员初始化赋值和初始化列表
- Mac OSX下编译 Hadoop 2.6.4
- windows7 + Redhat-server7.双系统中win7启动项丢失的解决
- 剑指offer面试题63 序列化二叉树(java实现)
- C语言指针使用不当带来的内存不可读
- 挑战程序竞赛系列(27):3.5二分图匹配(2)
- Android中获取应用程序(包)的信息----------PackageManager的使用一
- 使用ColorMatrix改变图片的饱和度
- JavaSE编程基础 第三章 控制语句
- 修改wamp的apache默认端口80以及www目录
- 抽取文本中的日期和时间
- JavaSE编程基础 第四章 数组
- HBase如何合理设置客户端Write Buffer
- 63. Unique Paths II