在网上找了一份挺好的模板,先标一下哦~链接君:http://blog.csdn.net/abcjennifer/article/details/5844579

#include <iostream>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
int max(int a,int b)
{return a<b?b:a;}

int min(int a,int b)
{return a<b?a:b;}

const int size = 160;
const int INF = 100000000;

bool map[size][size];         // 二分图的相等子图, map[i][j] = true 代表Xi与Yj有边
bool sx[size], sy[size]; // 标记在一次DFS中,Xi与Yi是否在交错树上
int match[size];             // 保存匹配信息,其中i为Y中的顶点标号,match[i]为X中顶点标号

bool DFS(int, const int);
void KM_Perfect_Match(const int n, const int edge[][size])
{
    int i, j;
    int lx[size], ly[size];   // KM算法中Xi与Yi的标号
    for(i = 0; i < n; i++)
    {
        lx[i] = -INF;
        ly[i] = 0;
        for(j = 0; j < n; j++)
        {
            lx[i] = max(lx[i], edge[i][j]);
        }
    }
    bool perfect = false;
    while(!perfect) 
    {
        // 初始化邻接矩阵
        for(i = 0; i < n; i++)
        {
            for(j = 0; j < n; j++) 
            {
                if(lx[i]+ly[j] == edge[i][j])
                    map[i][j] = true;
                else map[i][j] = false;
            }
        }
        // 匹配过程
        int live = 0;
        memset(match, -1, sizeof(match));
        for(i = 0; i < n; i++) {
            memset(sx, false, sizeof(sx));
            memset(sy, false, sizeof(sy));
            if(DFS(i, n)) live++;
            else {
                sx[i] = true;
                break;
            }
        }
        if(live == n) perfect = true;
        else {
            // 修改标号过程
            int ex = INF;
            for(i = 0; i < n; i++) 
            {
                for(j = 0; sx[i] && j < n; j++) 
                {
                    if(!sy[j]) 
                        ex = min(ex, lx[i]+ly[j]-edge[i][j]);
                }
            }
            for(i = 0; i < n; i++) 
            {
                if(sx[i]) lx[i] -= ex;
                if(sy[i]) ly[i] += ex;
            }
        }
    }
}

bool DFS(int p, const int n)//find augment path from X[p]
{
    int i;
    for(i = 0; i < n; i++)
    {
        if(!sy[i] && map[p][i]) 
        {
            sy[i] = true;
            int t = match[i];
            match[i] = p;
            if(t == -1 || DFS(t, n))
            {
                return true;
            }
            match[i] = t;
            if(t != -1) sx[t] = true;
        }
    }
    return false;
}

int main()
{
    int n, edge[size][size]; // edge[i][j]为连接Xi与Yj的边的权值
    int i;
    int m;
    /***************************************************
    *       record edge[i][j] as edge value between vertex i in X and vertex j in Y
    *       save n as vertexs need to be match (used in KM_Perfect_Match(n, edge);)
    ***************************************************/
    int s,d,pow;

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0 && m==0) break;
        memset(edge,0,sizeof(edge));
        /*最小权: 去掉memset(edge,0,sizeof(edge));改为如下:
        for(i=0;i<n;i++)
            for(int j=0;j<n;j++)
                edge[i][j]=-INF;
        */
        memset(sx,0,sizeof(sx));
        memset(sy,0,sizeof(sy));
        memset(match,0,sizeof(0));
        while(m--)
        {
            scanf("%d%d%d",&s,&d,&pow);
            s--;d--;
            /*最小权:edge[s][d]=pow; 改为edge[s][d]= - pow;*/
            edge[s][d]=pow;
        }
        KM_Perfect_Match(n, edge);
        int cost = 0;
        for(i=0;i<n;i++) 
        {
            cost += edge[match[i]][i];
        }
        /*最小权:output 改为 -cost*/
        cout<<cost<<endl;
    }
    // cost 为最大匹配的总和, match[]中保存匹配信息
    return 0;
}
View Code

相关文章: