最大流算法(Shortest Augmenting Path):
package problem1087; import java.util.ArrayList; import java.util.LinkedList; import java.util.Scanner; public class MainMaxFlow_SAP { static int recptNum; static int [] recpt; static int deviceNum; static int [] device; static int adapterNum; static int typeNum; static int nodeNum; static int pluggedIn = 0; static int [] prev; static int [][] capaMat; static final int INFINITE = 100000; static ArrayList<String> type = new ArrayList<String>(); /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); recptNum = scanner.nextInt(); recpt = new int[recptNum]; String s = scanner.nextLine(); for(int i = 0; i < recptNum; i++) { s = scanner.nextLine().trim(); recpt[i] = findType(s); } deviceNum = scanner.nextInt(); device = new int[deviceNum]; s = scanner.nextLine(); for(int i = 0; i < deviceNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); device[i] = findType(temp[1]); } adapterNum = scanner.nextInt(); s = scanner.nextLine(); int [] indexArr = new int[2 * adapterNum]; for(int i = 0; i < adapterNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); indexArr[2 * i] = findType(temp[0]); indexArr[2 * i + 1] = findType(temp[1]); } typeNum = type.size(); nodeNum = 2 + typeNum + deviceNum;//s, typeNum, deviceNum, t capaMat = new int[nodeNum][nodeNum]; prev = new int[nodeNum]; initCapaMat(indexArr); SAP(); System.out.println(deviceNum - pluggedIn); } static int findType(String s) { if(type.contains(s)) return type.indexOf(s); else { type.add(s); return type.size() - 1; } } static void initCapaMat(int [] indexArr) { for(int i = 0; i < nodeNum; i++) { for(int j = 0; j < nodeNum; j++) capaMat[i][j] = 0; } //from t to all receptacles for(int i = 0; i < recptNum; i++) { capaMat[0][1 + recpt[i]]++; } //from all devices to t && from receptacles to devices for(int i = 0; i < deviceNum; i++) { capaMat[1 + device[i]][1 + typeNum + i] = INFINITE; capaMat[1 + typeNum + i][nodeNum - 1] = 1; } //conversion from one receptacle to another for(int i = 0; i < adapterNum; i++) { capaMat[1 + indexArr[2 * i + 1]][1 + indexArr[2 * i]] = INFINITE; } } static void SAP() { while(true) { int augmented = BFS(); if(augmented == 0) break; else augment(augmented); } } static void augment(int augmented) { pluggedIn += augmented; int startIndex = prev[nodeNum - 1]; int endIndex = nodeNum - 1; while(true) { capaMat[startIndex][endIndex] -= augmented; capaMat[endIndex][startIndex] += augmented; if(startIndex == 0) return; endIndex = startIndex; startIndex = prev[startIndex]; } } static int BFS() { int augmented = 0; resetPrev(); LinkedList<Integer> queue = new LinkedList<Integer>(); queue.addLast(0); while(queue.size() > 0) { int fromIndex = queue.remove(); for(int i = 0; i < nodeNum; i++) { if((capaMat[fromIndex][i] > 0 ) && prev[i] == -1) { queue.addLast(i); prev[i] = fromIndex; if(augmented == 0) augmented = capaMat[fromIndex][i]; else augmented = Math.min(augmented, capaMat[fromIndex][i]); if(i == nodeNum - 1) return augmented; } } } return 0; } static void resetPrev() { for(int i = 0; i < prev.length; i++) prev[i] = -1; } }
最大流算法(Improved Shortest Augmenting Path):
package problem1087; import java.util.ArrayList; import java.util.LinkedList; import java.util.Scanner; public class MainMaxFlow_ISAP { static int recptNum; static int [] recpt; static int deviceNum; static int [] device; static int adapterNum; static int typeNum; static int nodeNum; static int pluggedIn = 0; static int [] prev; static int [] d; static int [] currentArc; static int [][] capaMat; static int currentNode; static final int INFINITE = 100000; static ArrayList<String> type = new ArrayList<String>(); /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); recptNum = scanner.nextInt(); recpt = new int[recptNum]; String s = scanner.nextLine(); for(int i = 0; i < recptNum; i++) { s = scanner.nextLine().trim(); recpt[i] = findType(s); } deviceNum = scanner.nextInt(); device = new int[deviceNum]; s = scanner.nextLine(); for(int i = 0; i < deviceNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); device[i] = findType(temp[1]); } adapterNum = scanner.nextInt(); s = scanner.nextLine(); int [] indexArr = new int[2 * adapterNum]; for(int i = 0; i < adapterNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); indexArr[2 * i] = findType(temp[0]); indexArr[2 * i + 1] = findType(temp[1]); } typeNum = type.size(); nodeNum = 2 + typeNum + deviceNum;//s, typeNum, deviceNum, t capaMat = new int[nodeNum][nodeNum]; prev = new int[nodeNum]; d = new int[nodeNum]; currentArc = new int[nodeNum]; initCapaMat(indexArr); ISAP(); System.out.println(deviceNum - pluggedIn); } static int findType(String s) { if(type.contains(s)) return type.indexOf(s); else { type.add(s); return type.size() - 1; } } static void initCapaMat(int [] indexArr) { for(int i = 0; i < nodeNum; i++) { for(int j = 0; j < nodeNum; j++) capaMat[i][j] = 0; } //from t to all receptacles for(int i = 0; i < recptNum; i++) { capaMat[0][1 + recpt[i]]++; } //from all devices to t && from receptacles to devices for(int i = 0; i < deviceNum; i++) { capaMat[1 + device[i]][1 + typeNum + i] = INFINITE; capaMat[1 + typeNum + i][nodeNum - 1] = 1; } //conversion from one receptacle to another for(int i = 0; i < adapterNum; i++) { capaMat[1 + indexArr[2 * i + 1]][1 + indexArr[2 * i]] = INFINITE; } } static void ISAP() { currentNode = 0; for(int i = 0; i < nodeNum; i++) { currentArc[i] = 1; } resetPrev(); revBFS(); while(d[0] < nodeNum) { int i; for(i = currentArc[currentNode]; i < nodeNum; i++) { if(d[currentNode] - d[i] == 1 && capaMat[currentNode][i] > 0) { break; } } if(i < nodeNum) { currentArc[currentNode] = i; advance(i); if(currentNode == nodeNum - 1) { augment(); currentNode = 0; } } else { currentArc[currentNode] = 1; retreat(); } } } private static void retreat() { d[currentNode] = nodeNum; for(int i = 0; i < nodeNum; i++) { if(capaMat[currentNode][i] > 0) { d[currentNode] = Math.min(d[currentNode], d[i] + 1); } } if(currentNode != 0) { currentNode = prev[currentNode]; } } private static void advance(int nextNode) { prev[nextNode] = currentNode; currentNode = nextNode; } static void augment() { int startIndex = prev[nodeNum - 1]; int endIndex = nodeNum - 1; int min = INFINITE + 1; while(true) { min = Math.min(min, capaMat[startIndex][endIndex]); if(startIndex == 0) break; endIndex = startIndex; startIndex = prev[startIndex]; } pluggedIn += min; startIndex = prev[nodeNum - 1]; endIndex = nodeNum - 1; while(true) { capaMat[startIndex][endIndex] -= min; capaMat[endIndex][startIndex] += min; if(startIndex == 0) break; endIndex = startIndex; startIndex = prev[startIndex]; } } static void revBFS() { for(int i = 0; i < nodeNum; i++) d[i] = nodeNum; d[nodeNum - 1] = 0; LinkedList<Integer> queue = new LinkedList<Integer>(); queue.addLast(nodeNum - 1); while(queue.size() > 0) { int fromIndex = queue.remove(); for(int i = 0; i < nodeNum; i++) { if((capaMat[i][fromIndex] > 0) && (d[i] == nodeNum)) { d[i] = d[fromIndex] + 1; queue.addLast(i); } } } } static void resetPrev() { for(int i = 0; i < prev.length; i++) prev[i] = -1; } }
最大二分匹配:
package problem1087; import java.util.ArrayList; import java.util.Scanner; public class MainMaximalMatching { static int recptNum; static int [] recpt; static int deviceNum; static int [] device; static boolean [] used; static int [] link; static int typeNum; static int [][] connMat; static ArrayList<String> type = new ArrayList<String>(); /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); recptNum = scanner.nextInt(); recpt = new int[recptNum]; String s = scanner.nextLine(); for(int i = 0; i < recptNum; i++) { s = scanner.nextLine().trim(); recpt[i] = findType(s); } deviceNum = scanner.nextInt(); device = new int[deviceNum]; used = new boolean[deviceNum]; link = new int[deviceNum]; s = scanner.nextLine(); for(int i = 0; i < deviceNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); device[i] = findType(temp[1]); } int adapterNum = scanner.nextInt(); s = scanner.nextLine(); int [] indexArr = new int[2 * adapterNum]; for(int i = 0; i < adapterNum; i++) { s = scanner.nextLine().trim(); String [] temp = s.split(" "); indexArr[2 * i] = findType(temp[0]); indexArr[2 * i + 1] = findType(temp[1]); } buildConnMat(); for(int i = 0; i < adapterNum; i++) { int recptIndex = indexArr[2 * i]; int plugIndex = indexArr[2 * i + 1]; connMat[plugIndex][recptIndex] = 1; } FloydWarshall(); Hungary(); int ctr = 0; for(int i = 0; i < deviceNum; i++) { if(link[i] == -1) ctr++; } System.out.println(ctr); } static int findType(String s) { if(type.contains(s)) return type.indexOf(s); else { type.add(s); return type.size() - 1; } } static void Hungary() { for(int i = 0; i < deviceNum; i++) { link[i] = -1; } for(int i = 0; i < recptNum; i++) { for(int j = 0; j < deviceNum; j++) used[j] = false; findPath(i); } } static boolean findPath(int index) { for(int i = 0; i < deviceNum; i++) { if(connMat[recpt[index]][device[i]] == 1 && !used[i]) { used[i] = true; if(link[i] == -1 || findPath(link[i])) { link[i] = index; return true; } } } return false; } static void FloydWarshall() { for(int k = 1; k < typeNum; k++) { for(int i = 0; i < typeNum; i++) { if(connMat[i][k] == 0) continue; for(int j = 0; j < typeNum; j++) { if(connMat[k][j] == 0) continue; connMat[i][j] = 1; } } } } static void buildConnMat() { typeNum = type.size(); connMat = new int[typeNum][typeNum]; for(int i = 0; i < typeNum; i++) { for(int j = 0; j < typeNum; j++) { if(i == j) connMat[i][j] = 1; else connMat[i][j] = 0; } } } }