先上例题
杭电acm 2063 :http://acm.hdu.edu.cn/showproblem.php?pid=2063
bool 寻找从k出发的对应项出的可增广路 { while (从邻接表中列举k能关联到顶点j) { if (j不在增广路上) { 把j加入增广路; if (j是未盖点 或者 从j的对应项出发有可增广路) { 修改j的对应项为k; 则从k的对应项出有可增广路,返回true; } } } 则从k的对应项出没有可增广路,返回false; } void 匈牙利hungary() { for i->1 to n { if (则从i的对应项出有可增广路) 匹配数++; } 输出 匹配数; }
附上题解代码
import java.util.*; public class Main { public int map[][]=new int [1010][1010];//男生和女的有关系数 public int match[]=new int[1010]; //是否已经匹配数 public int used[]=new int [1010]; //是否有关系 public boolean find(int x,int n ){ for(int i=1;i<=n;i++){ if(used[i]==0&&map[x][i]==1){ //如果没有i男生是空闲的且x,i有关系 used[i]=1; if(match[i]==-1||find(match[i],n)){ //如果i男生没有匹配或者她放弃男生i并且另外找到了自己的伴 match[i]=x; return true; } } }return false; } //该函数判断女生爱能不能找到伴 public static void main(String[] args) { Scanner sc=new Scanner(System.in); int k,m,n; while(sc.hasNext()){ k=sc.nextInt(); if(k==0) System.exit(0); m=sc.nextInt(); n=sc.nextInt(); int cnt=0; Main lei=new Main(); Arrays.fill(lei.match,-1); for(int i=0;i<lei.map.length;i++){ for(int j=0;j<lei.map.length;j++){ lei.map[i][j]=0; } } for(int i=1;i<=k;i++){ int a,b; a=sc.nextInt(); b=sc.nextInt(); lei.map[a][b]=1; } for(int i=1;i<=m;i++){ Arrays.fill(lei.used,0); if(lei.find(i,n)) cnt++; } System.out.println(cnt); } } }
匈牙利算法精髓就是尽可能的多占,可以通过回溯来试,不过当试的时候破坏了之前的安排,则是无能为力的,只能要求尽可能的多。
杭电3020
package demo2; import java.util.*; public class Main6 { static int edge[][]=new int [1005][1005]; static int num_map[][]=new int [1000][1001]; static char map[][]=new char[1000][1001]; static int cx[]=new int[505]; static int cy[]=new int[505]; static int vis[]=new int[505]; static int match[]=new int[505]; static int N,K,M; static int d[][]={{-1,0},{1,0},{0,-1},{0,1}}; public static int path(int u){ int v; for(v=1;v<=M;v++){ if(vis[v]==0&&edge[u][v]==1){ vis[v]=1; if(match[v]==-1||path(match[v])==1){ match[v]=u; return 1; } } } return 0; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); N = sc.nextInt(); while(N-->0){ int count=0; for(int i=0;i<num_map.length;i++) Arrays.fill(num_map[i], 0); for(int i=0;i<edge.length;i++) Arrays.fill(edge[i], 0); int m= sc.nextInt(); int k = sc.nextInt(); sc.nextLine(); for(int i=0;i<m;i++){ String s = sc.nextLine(); map[i]=s.toCharArray(); } // int res=0; int num=0; for(int i=0;i<m;i++){ for(int j=0;j<k;j++){ // System.out.print([i][j]); if(map[i][j]=='*'){ num_map[i][j]=++num; // System.out.println(num_map[i][j]); } } // System.out.println(); } K=num;M=num; System.out.println(num); for(int i=0;i<m;i++){ for(int j=0;j<k;j++){ if(num_map[i][j]!=0){ // System.out.println(num_map[i][j]); for(int c=0;c<4;c++){ int x = i+d[c][0]; int y = j+d[c][1]; if(x<0||y<0||x>=m||y>=k) continue; if(num_map[x][y]!=0) edge[num_map[i][j]][num_map[x][y]]=1; } } } } // for(int i=1;i<=m;i++){ // for(int j=1;j<=k;j++){ // System.out.print(num_map[i][j]); // } // System.out.println(); // } Arrays.fill(match, -1); for(int i=1;i<=K;i++){ Arrays.fill(vis, 0); if(path(i)==1) count++; } System.out.println(num-count/2); } } }