HDU 3488 Tour(拆点+最优匹配)

思路:以前对二分图的理解还不够、现在加深了对匹配的理解、完全匹配图就是n个环的并,所以求的是完美匹配中的最小权问题、直接KM算法

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x7ffffff
const int N=205;
int mpt[N][N];
int lx[N];
int ly[N];
int match[N];
bool visitx[N];
bool visity[N];
int n,m;
int hungary(int x)
{
    visitx[x]=true;
    for(int i=1;i<=n;i++)
    {
        if(!visity[i]&&lx[x]+ly[i]==mpt[x][i])
        {
            visity[i]=true;
            if(match[i]==-1||hungary(match[i]))
            {
                match[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
void KM_perfect_match()
{
    memset(match,-1,sizeof(match));
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            lx[i]=max(lx[i],mpt[i][j]);
    for(int i=1;i<=n;i++)
    {

        while(1)
        {
            memset(visitx,false,sizeof(visitx));
            memset(visity,false,sizeof(visity));
            if(hungary(i))break;
            else
            {
                int temp=INF;
                for(int j=1;j<=n;j++)
                {
                    if(visitx[j])
                    {
                        for(int k=1;k<=n;k++)
                        {
                            if(!visity[k]&&temp>(lx[j]+ly[k]-mpt[j][k]))
                                temp=lx[j]+ly[k]-mpt[j][k];
                        }
                    }
                }
                for(int j=1;j<=n;j++)
                {
                    if(visitx[j])lx[j]-=temp;
                    if(visity[j])ly[j]+=temp;
                }
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(mpt,0x80,sizeof(mpt));
        for(int i=1;i<=m;i++)
        {
            int u,v,c;
            scanf("%d%d%d",&u,&v,&c);
            mpt[u][v]=max(-c,mpt[u][v]);
        }
        KM_perfect_match();
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            sum+=mpt[match[i]][i];
        }
        printf("%d\n",-sum);
    }
    return 0;
}


你可能感兴趣的:(最优匹配)