最大流算法(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;
}
}
}
}