带权二分图的最大权匹配 KM算法模版

带权二分图的最大权匹配 KM算法模版

下面是kuangbin大神的模版,已通过西电oj1048的测试

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<vector>

#include<stack>

#include<queue>

#include<set>

#include<map>

#include<string>

#include<math.h>

#include<cctype>

 

using namespace std;

 

typedef long long ll;

const int maxn=550;

const int INF=(1<<29);

const double EPS=0.0000000001;

const double Pi=acos(-1.0);

 

int G[maxn][maxn];

int m;

int nx,ny;

int link[maxn],lx[maxn],ly[maxn];

int slack[maxn];

bool visx[maxn],visy[maxn];

 

bool dfs(int x)

{

    visx[x]=1;

    for(int y=0;y<ny;y++){

        if(visy[y]) continue;

        int tmp=lx[x]+ly[y]-G[x][y];

        if(tmp==0){

            visy[y]=1;

            if(link[y]==-1||dfs(link[y])){

                link[y]=x;

                return true;

            }

        }

        else if(slack[y]>tmp) slack[y]=tmp;

    }

    return false;

}

 

int KM()

{

    memset(link,-1,sizeof(link));

    memset(ly,0,sizeof(ly));

    for(int i=0;i<nx;i++){

        lx[i]=-INF;

        for(int j=0;j<ny;j++){

            if(G[i][j]>lx[i]) lx[i]=G[i][j];

        }

    }

    for(int x=0;x<nx;x++){

        for(int i=0;i<ny;i++) slack[i]=INF;

        while(1){

            memset(visx,0,sizeof(visx));

            memset(visy,0,sizeof(visy));

            if(dfs(x)) break;

            int d=INF;

            for(int i=0;i<ny;i++){

                if(!visy[i]&&d>slack[i]) d=slack[i];

            }

            for(int i=0;i<nx;i++){

                if(visx[i]) lx[i]-=d;

            }

            for(int i=0;i<ny;i++){

                if(visy[i]) ly[i]+=d;

                else slack[i]-=d;

            }

        }

    }

    int res=0;

    for(int i=0;i<ny;i++){

        if(link[i]!=-1) res+=G[link[i]][i];

    }

    return res;

}

 

int main()

{

    while(cin>>nx>>ny){

        memset(G,0,sizeof(G));

        cin>>m;

        while(m--){

            int u,v;

            scanf("%d%d",&u,&v);

            G[u][v]=1;

        }

        cout<<KM()<<endl;

    }

    return 0;

}
View Code

 

你可能感兴趣的:(二分图)