模板——二分图匹配KM

具体方法就不介绍了,详见 https://blog.csdn.net/sixdaycoder/article/details/47720471

主要讲一些注意点:

1:slack开外面节省时间,因为同一个x在不停循环中slack只会不断变小,被更新

2:因为多组数据,所有数组都记得清零

3:dfs中坑了我20多次MLE……记得visx,visy数组都要更新

4:这种做法仅限于每一个点都能被匹配的情况,若不能都匹配就要用网络流

二分图匹配模板题:(值得思考)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int V,n,m,e;
 4 vector<int> v[1005];
 5 int vis[1005],match[1005];
 6  
 7 int init()
 8 {
 9     memset(match,-1,sizeof(match));
10     scanf("%d%d%d%d",&V,&n,&m,&e);
11     for(int i=1;i<=e;i++)
12     {
13         int x,y;
14         scanf("%d%d",&x,&y); y+=n;
15         v[x].push_back(y);
16     }
17 }
18  
19 int dfs(int u)
20 {
21     for(int i=0;i<(int)v[u].size();i++)
22     {
23         int p=v[u][i];
24         if(vis[p]) continue;
25         vis[p]=1;
26         if(match[p]==-1||dfs(match[p])==1)
27         {
28             match[u]=p;
29             match[p]=u;
30             return 1;
31         }
32     }
33     return 0;
34 }
35  
36 int main()
37 {
38     int sum=0;
39     init();
40     for(int i=1;i<=n;i++)
41     {
42         if(match[i]==-1)
43         {
44             memset(vis,0,sizeof(vis));
45             if (dfs(i)) sum++;
46         }
47     }
48     printf("%d\n",min(V+1,n+m-sum));
49     return 0;
50 }
View Code

KM模板题

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=305;
 5 const int inf=0X3f3f3f;
 6 
 7 int w[N][N];
 8 int n,ans=0;
 9 int lx[N],ly[N],match[N],slack[N];
10 bool visx[N],visy[N];
11 
12 
13 void init()
14 {
15     for(int i=0;i<n;i++) visy[i]=0;
16     for(int i=0;i<n;i++) visx[i]=0;
17 }
18 
19 bool dfs(int u)
20 {
21     int Delta;
22     visx[u]=1;
23     for(int v=0;v<n;++v)
24     {
25         if(visy[v]) continue;
26         Delta=lx[u]+ly[v]-w[u][v];
27         if(Delta==0)
28         {
29             visy[v]=1;
30             if(match[v]==-1||dfs(match[v]))
31             {
32                 match[v]=u;
33                 return true;
34             }
35         }
36         else if(slack[v] > Delta)
37             slack[v] = Delta;
38     }
39     return false;    
40 }
41 
42 void KM()
43 {
44     for(int x=0;x<n;++x)
45     {
46         for(int y=0;y<n;++y) slack[y]=inf;//开外面节省时间 
47         while(true)
48         {
49             init();
50             if(dfs(x)) break;
51             int delta=inf;
52             for(int j=0;j<n;++j) if(!visy[j]&&delta>slack[j]) delta=slack[j];
53             for(int i=0;i<n;++i) if(visx[i]) lx[i]-=delta;
54             for(int j=0;j<n;++j) 
55             {
56                 if(visy[j]) ly[j]+=delta;
57                 else slack[j]-=delta;
58             }
59         }
60     }
61 }
62 
63 int main()
64 {
65     while(scanf("%d",&n)!=EOF)
66     {
67         memset(match,-1,sizeof(match));
68         memset(ly,0,sizeof(ly));
69         for(int i=0;i<n;++i) match[i]=-1;
70         for(int i=0;i<n;++i)
71         {
72             for(int j=0;j<n;++j)
73                {
74                 scanf("%d",&w[i][j]);
75             }
76         }
77         for(int i=0;i<n;++i)
78         {
79             lx[i]=-inf;
80             for(int j=0;j<n;j++) if(lx[i]<w[i][j]) lx[i]=w[i][j];
81         }
82         KM();
83     
84         ans=0;
85         for(int i=0;i<n;++i)
86         {
87             if(match[i]!=-1) ans+=w[match[i]][i];
88         }
89         printf("%d\n",ans);
90     }
91     return 0;
92 }
View Code

猜你喜欢

转载自www.cnblogs.com/Forever-666/p/10980686.html