ACM HDOJ 1068 (Girls and Boys)

来源:互联网 发布:sap hybris数据库 编辑:程序博客网 时间:2024/06/04 19:59

题目链接

思路 二分图的最大独立集数 = 节点数 - 最大匹配数,这道题目在计算最大匹配数时有重复计算的,所以得到的最大匹配数还要除以2

程序一 匈牙利算法 DFS

import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int leftSetNumber = Integer.parseInt(scn.next());int rightSetNumber = leftSetNumber;Hungary hungary = new Hungary(leftSetNumber, rightSetNumber);for (int i = 0; i < leftSetNumber; ++i) {String leftString = scn.next();int left = Integer.parseInt(leftString.substring(0,leftString.length() - 1));String rightString = scn.next();int rightNumber = Integer.parseInt(rightString.substring(1,rightString.length() - 1));for (int j = 0; j < rightNumber; ++j) {int right = Integer.parseInt(scn.next());hungary.addEdge(left, right);}}System.out.println(rightSetNumber - hungary.maxMatch() / 2);}scn.close();}}class Hungary {private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private boolean searchPath(int left) {for (int right = 0; right < rightSetNumber; ++right) {if (matrix[left][right] && !rightUsed[right]) {rightUsed[right] = true;if (-1 == rightResult[right] || searchPath(rightResult[right])) {rightResult[right] = left;leftResult[left] = right;return true;}}}return false;}public Hungary(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);Arrays.fill(rightUsed, false);int count = 0;for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left]) {Arrays.fill(rightUsed, false);if (searchPath(left)) {++count;}}}return count;}}

程序二 匈牙利算法 BFS

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int leftSetNumber = Integer.parseInt(scn.next());int rightSetNumber = leftSetNumber;Hungary hungary = new Hungary(leftSetNumber, rightSetNumber);for (int i = 0; i < leftSetNumber; ++i) {String leftString = scn.next();int left = Integer.parseInt(leftString.substring(0,leftString.length() - 1));String rightString = scn.next();int rightNumber = Integer.parseInt(rightString.substring(1,rightString.length() - 1));for (int j = 0; j < rightNumber; ++j) {int right = Integer.parseInt(scn.next());hungary.addEdge(left, right);}}System.out.println(rightSetNumber - hungary.maxMatch() / 2);}scn.close();}}class Hungary {private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private int[] preLeft;public Hungary(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];preLeft = new int[leftSetNumber];}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);Arrays.fill(preLeft, -1);int count = 0;for (int i = 0; i < leftSetNumber; ++i) {if (-1 == leftResult[i]) {Queue<Integer> queue = new LinkedList<Integer>();queue.offer(i);boolean hasAP = false;Arrays.fill(rightUsed, false);while (!queue.isEmpty() && !hasAP) {int left = queue.poll();for (int right = 0; right < rightSetNumber && !hasAP; ++right) {if (matrix[left][right] && !rightUsed[right]) {rightUsed[right] = true;queue.offer(rightResult[right]);if (0 <= rightResult[right]) {preLeft[rightResult[right]] = left;} else {hasAP = true;int currentLeft = left;int currentRight = right;while (-1 != currentLeft) {int lastRight = leftResult[currentLeft];leftResult[currentLeft] = currentRight;rightResult[currentRight] = currentLeft;currentLeft = preLeft[currentLeft];currentRight = lastRight;}}}}}if (-1 != leftResult[i]) {++count;}}}return count;}}

程序三 Hopcroft-Carp 算法

import java.util.Arrays;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scn = new Scanner(System.in);while (scn.hasNext()) {int edgesNumber = Integer.parseInt(scn.next());if (0 == edgesNumber) {break;}int leftSetNumber = Integer.parseInt(scn.next());int rightSetNumber = Integer.parseInt(scn.next());HopcroftCarp hopcroftCarp = new HopcroftCarp(leftSetNumber,rightSetNumber);for (int i = 0; i < edgesNumber; ++i) {int left = Integer.parseInt(scn.next()) - 1;int right = Integer.parseInt(scn.next()) - 1;hopcroftCarp.addEdge(left, right);}System.out.println(hopcroftCarp.maxMatch());}scn.close();}}class HopcroftCarp {private final int INF = Integer.MAX_VALUE / 2;private int leftSetNumber;private int rightSetNumber;private boolean[][] matrix;private int[] leftResult;private int[] rightResult;private boolean[] rightUsed;private int[] leftGradation;private int[] rightGradation;private int gradation;private boolean searchPath() {Arrays.fill(leftGradation, -1);Arrays.fill(rightGradation, -1);gradation = INF;Queue<Integer> queue = new LinkedList<Integer>();for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left]) {queue.offer(left);++leftGradation[left];}}while (!queue.isEmpty()) {int left = queue.poll();if (leftGradation[left] > gradation) {break;}for (int right = 0; right < rightSetNumber; ++right) {if (matrix[left][right] && -1 == rightGradation[right]) {rightGradation[right] = leftGradation[left] + 1;if (-1 == rightResult[right]) {gradation = rightGradation[right];} else {leftGradation[rightResult[right]] = rightGradation[right] + 1;queue.offer(rightResult[right]);}}}}return INF != gradation;}private boolean dfs(int left) {for (int right = 0; right < rightSetNumber; right++) {if (!rightUsed[right] && matrix[left][right]&& rightGradation[right] == leftGradation[left] + 1) {rightUsed[right] = true;if (-1 != rightResult[right]&& rightGradation[right] == gradation) {continue;}if (-1 == rightResult[right] || dfs(rightResult[right])) {rightResult[right] = left;leftResult[left] = right;return true;}}}return false;}public HopcroftCarp(int leftSetNumber, int rightSetNumber) {this.leftSetNumber = leftSetNumber;this.rightSetNumber = rightSetNumber;matrix = new boolean[leftSetNumber][rightSetNumber];leftResult = new int[leftSetNumber];rightResult = new int[rightSetNumber];rightUsed = new boolean[rightSetNumber];leftGradation = new int[leftSetNumber];rightGradation = new int[rightSetNumber];gradation = INF;}public void addEdge(int left, int right) {matrix[left][right] = true;}public int maxMatch() {Arrays.fill(leftResult, -1);Arrays.fill(rightResult, -1);int count = 0;while (searchPath()) {Arrays.fill(rightUsed, false);for (int left = 0; left < leftSetNumber; ++left) {if (-1 == leftResult[left] && dfs(left)) {++count;}}}return count;}}

0 0
原创粉丝点击