首页 > 代码库 > 贴板子系列_1-km算法,匈牙利算法

贴板子系列_1-km算法,匈牙利算法

KM算法
技术分享
 1 #include <bits/stdc++.h>
 2 #define N 1500
 3 #define inf 999999999
 4 using namespace std;
 5 int a[N],bs[N],nx=0,ny=0,k;
 6 int linky[N],lx[N],ly[N],slack[N];
 7 int visx[N],visy[N],w[N][N];
 8 int min(int a,int b){return (a<b)?a:b;}
 9 int find(int x){
10     visx[x]=1;
11     for(int y=1;y<=ny;y++){
12         if(visy[y]) continue;
13         int t=lx[x]+ly[y]-w[x][y];
14         if(t==0){visy[y]=1;
15             if(linky[y]==-1||find(linky[y])){
16                 linky[y]=x;return 1;
17             }
18         }
19         else if(slack[y]>t) slack[y]=t;
20     }
21     return 0;
22 }
23 int km(){
24     memset(linky,-1,sizeof(linky));
25     memset(ly,0,sizeof(ly));
26     for(int i=1;i<=nx;i++) lx[i]=-inf;
27     for(int i=1;i<=nx;i++)for(int j=1;j<=ny;j++)if(w[i][j]>lx[i])lx[i]=w[i][j];
28     for(int x=1;x<=nx;x++){
29         for(int i=1;i<=ny;i++)
30             slack[i]=inf;
31         while(1){
32             memset(visx,0,sizeof(visx));
33             memset(visy,0,sizeof(visy));
34             if(find(x)) break;
35             int d=inf;
36             for(int i=1;i<=ny;i++) if(!visy[i]&&d>slack[i]) d=slack[i];
37             for(int i=1;i<=nx;i++) if(visx[i]) lx[i]-=d;
38             for(int i=1;i<=ny;i++) if(visy[i]) ly[i]+=d; else slack[i]-=d;
39         }
40     }
41     int result=0;
42     for(int i=1;i<=ny;i++)
43     if(linky[i]>-1) result+=w[linky[i]][i];
44     return result;
45 }
46 int main(){
47     scanf("%d%d%d",&nx,&ny,&k);
48     for(int i=1;i<=k;i++){
49         int a,b,c;scanf("%d%d%d",&a,&b,&c);
50         w[a][b]=c;
51     }printf("%d\n",km());
52     return 0;
53 }
View Code

 

匈牙利算法
技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #define N 1010
 4 using namespace std;
 5 int map[N][N];
 6 int max,x1,m,y1,tot,ans;
 7 int used[N],link[N];
 8 int find(int t)
 9 {
10     for(int i=1;i<=y1;i++)
11     {
12         if(used[i]==0&&map[t][i]==1)
13         {
14             used[i]=1;
15             if(link[i]==0||find(link[i]))
16             {
17                 link[i]=t;
18                 return 1;
19             }
20         }
21     }
22     return 0;
23 }
24 int main()
25 {
26     scanf("%d%d%d%d",&max,&x1,&y1,&m);
27     max++;tot=x1+y1;
28     for(int i=1;i<=m;i++)
29     {
30         int a,b;
31         scanf("%d%d",&a,&b);
32         map[a][b]=1;
33     }
34     for(int i=1;i<=y1;i++)link[i]=0;
35     for(int i=1;i<=x1;i++)
36     {
37         for(int i=1;i<=y1;i++) used[i]=0;
38         if(find(i))
39             ans++;
40     }
41     printf("%d\n",(max<tot-ans)? max:tot-ans);
42     return 0;
43 }
View Code

贴板子系列_1-km算法,匈牙利算法