模板——二分图匹配KM

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

主要讲一些注意点:

1:不直接将未匹配的y减小是因为要保证lx[i]+ly[j]>=w[i][j],证明详见上述博客

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

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

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

5:只有在值相等时才能赋值visy

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

 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模板题

#include<cstdio>
#include<cstring>
using namespace std;
const int N=305;
const int inf=0X3f3f3f;

int w[N][N];
int n,ans=0;
int lx[N],ly[N],match[N],slack[N];
bool visx[N],visy[N];


void init()
{
    for(int i=0;i<n;i++) visy[i]=0;
    for(int i=0;i<n;i++) visx[i]=0;
}

bool dfs(int u)
{
    int Delta;
    visx[u]=1;
    for(int v=0;v<n;++v)
    {
        if(visy[v]) continue;
        Delta=lx[u]+ly[v]-w[u][v];
        if(Delta==0)
        {
            visy[v]=1;
            if(match[v]==-1||dfs(match[v]))
            {
                match[v]=u;
                return true;
            }
        }
        else if(slack[v] > Delta)
            slack[v] = Delta;
    }
    return false;
}

void KM()
{
    for(int x=0;x<n;++x)
    {
        for(int y=0;y<n;++y) slack[y]=inf; 
        while(true)
        {
            init();
            if(dfs(x)) break;
            int delta=inf;
            for(int j=0;j<n;++j) if(!visy[j]&&delta>slack[j]) delta=slack[j];
            for(int i=0;i<n;++i) if(visx[i]) lx[i]-=delta;
            for(int j=0;j<n;++j) 
            {
                if(visy[j]) ly[j]+=delta;
                else slack[j]-=delta;//important
            }
        }
    }
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(match,-1,sizeof(match));
        memset(ly,0,sizeof(ly));
        for(int i=0;i<n;++i) match[i]=-1;
        for(int i=0;i<n;++i)
        {
            for(int j=0;j<n;++j)
               {
                scanf("%d",&w[i][j]);
            }
        }
        for(int i=0;i<n;++i)
        {
            lx[i]=-inf;
            for(int j=0;j<n;j++) if(lx[i]<w[i][j]) lx[i]=w[i][j];
        }
        KM();
    
        ans=0;
        for(int i=0;i<n;++i)
        {
            if(match[i]!=-1) ans+=w[match[i]][i];
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2019-06-05 17:07  'Clovers'  阅读(179)  评论(1编辑  收藏  举报