給定一個二分圖,其中左半部包含n1n1個點(編號1~n1n1),右半部包含n2n2個點(編號1~n2n2),二分圖共包含m條邊。java
數據保證任意一條邊的兩個端點都不可能在同一部分中。算法
請你求出二分圖的最大匹配數。spa
二分圖的匹配:給定一個二分圖G,在G的一個子圖M中,M的邊集{E}中的任意兩條邊都不依附於同一個頂點,則稱M是一個匹配。code
二分圖的最大匹配:全部匹配中包含邊數最多的一組匹配被稱爲二分圖的最大匹配,其邊數即爲最大匹配數。xml
第一行包含三個整數 n1n一、 n2n2 和 mm。blog
接下來m行,每行包含兩個整數u和v,表示左半部點集中的點u和右半部點集中的點v之間存在一條邊。class
輸出一個整數,表示二分圖的最大匹配數。import
1≤n1,n2≤5001≤n1,n2≤500,
1≤u≤n11≤u≤n1,
1≤v≤n21≤v≤n2,
1≤m≤1051≤m≤105im
2 2 4 1 1 1 2 2 1 2 2
時間複雜度O(mn) 實際運行時間通常遠小於O(mn)
代碼:2
//匈牙利算法 //思路:一個二分圖,從左邊子圖最多能找到右邊子圖一一匹配的最大數量 //對於左邊子圖的某點,找右邊子圖的某點;若是右邊連通的某點沒有被匹配,那麼能夠選擇該點做爲匹配點; //不然,右邊該點已經被匹配,則看看與右邊的這個點匹配的左邊的點可否還能找到另外一個匹配的右邊的點, //若是能,則把右邊這個點讓給當前待匹配的左邊的點 import java.util.Arrays; import java.util.Scanner; public class Main{ static final int N=505,M=100005; static int h[]=new int[N]; static int e[]=new int[M]; static int ne[]=new int[M]; static int n1,n2,m,idx; static int match[]=new int[N]; static boolean vis[]=new boolean[N]; static void add(int a,int b){ e[idx]=b; ne[idx]=h[a]; h[a]=idx++; } static boolean find(int u){ for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(!vis[j]){ vis[j]=true; if(match[j]==0 || find(match[j])){//右邊的該點沒有被匹配或者j對應的左邊的點能找到另外一個能匹配的右邊的點 match[j]=u; return true; } } } return false; } public static void main(String[] args) { Scanner scan=new Scanner(System.in); Arrays.fill(h, -1); n1=scan.nextInt(); n2=scan.nextInt(); m=scan.nextInt(); while(m-->0){ int a=scan.nextInt(); int b=scan.nextInt(); add(a,b);//咱們只從左邊向右邊查找 } int res=0; for(int i=1;i<=n1;i++){ Arrays.fill(vis, false);//初始化,對於每個左邊的點,一開始它都沒有匹配右邊的點 if(find(i)) res++; } System.out.println(res); } }