PKU ACM 1087(A Plug for UNIX)的两种解法:最大流和最大二分匹配(JAVA实现)

最大流算法(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;
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值