http://acm.hdu.edu.cn/showproblem.php?pid=2813

裸二分图最优匹配,需要用两个map把武将名字映射到点的序号上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
const int N=210;
const int INF=0x3f3f3f3f;
int nx,ny;
int linker[N],lx[N],ly[N],slack[N];  
int visx[N],visy[N],w[N][N];
int DFS(int x)
{
    visx[x]=1;
    for(int y=1;y<=ny;y++){
        if(visy[y])
            continue;
        int tmp=lx[x]+ly[y]-w[x][y];
        if(tmp==0){
            visy[y]=1;
            if(linker[y]==-1 || DFS(linker[y])){
                linker[y]=x;
                return 1;
            }
        }else if(slack[y]>tmp){ 
            slack[y]=tmp;
        }
    }
    return 0;
}
int KM()
{
    int i,j;
    memset(linker,-1,sizeof(linker));
    memset(ly,0,sizeof(ly));
    for(i=1;i<=nx;i++)      
        for(j=1,lx[i]=-INF;j<=ny;j++)
            if(w[i][j]>lx[i])
                lx[i]=w[i][j];
    for(int x=1;x<=nx;x++){
        for(i=1;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(i=1;i<=ny;i++)
                if(!visy[i] && d>slack[i])
                    d=slack[i];
            for(i=1;i<=nx;i++)
                if(visx[i])
                    lx[i]-=d;
            for(i=1;i<=ny;i++) 
                if(visy[i])
                    ly[i]+=d;
                else
                    slack[i]-=d;
        }
    }
    int res=0;
    for(i=1;i<=ny;i++)
        if(linker[i]!=-1)
            res+=w[linker[i]][i];
    return res;
}
int main()
{
    int n,m,k ;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        nx=n;ny=m;
        for(int i=0 ;i<N ;i++)
            for(int j=0 ;j<N ;j++)
                w[i][j]=-INF ;
          int p1=1,p2=1 ;
          map <string,int> mp1,mp2 ;
        for(int i=0 ;i<k ;i++)
        {
            char a[205],b[205] ;
            int v ;
            scanf("%s%s%d",a,b,&v) ;
            string s1(a),s2(b) ;
            if(!mp1[s1])mp1[s1]=p1++ ;
            if(!mp2[s2])mp2[s2]=p2++ ;
            w[mp1[s1]][mp2[s2]]=-v ;
        }
        int ans=KM();
        printf("%d\n",-ans);
    }    
    return 0;
}
View Code