zoukankan      html  css  js  c++  java
  • hdu 2255 奔小康赚大钱(最佳匹配)

    点击打开链接

    直接模版。。

    #include <stdio.h>
    #include <memory.h>
    #define Min(X,Y) X<=Y?X:Y;
    #define SIZE 305
    #define INF 0x7f7f7f7f
    long n;
    long match[SIZE],edge[SIZE][SIZE],lx[SIZE],ly[SIZE],slack[SIZE];
    char vstx[SIZE],vsty[SIZE];
    bool DFS(long x){
        long i;
        vstx[x]=1;             //访问标志置1
        for(i=0;i<n;i++){
            if(vsty[i]==0&&edge[x][i]==lx[x]+ly[i]){
                vsty[i]=1;
                if(match[i]==-1||DFS(match[i])){    //i没被访问过可直接构造或者通过该点能间接构造增广路
                    match[i]=x;
                    return true;
                }
            }
            else if(edge[x][i]!=lx[x]+ly[i])        //不能构造增广路,松驰对应值
                slack[i]=Min(slack[i],lx[x]+ly[i]-edge[x][i]);
        }
        return false;
    }
    long KM(){
        long i,j,sum,mn;
        memset(match,-1,sizeof(match[0])*n);
        for(i=0;i<n;i++){
            while(1){
                memset(vstx,0,sizeof(vstx[0])*n);
                memset(vsty,0,sizeof(vsty[0])*n);
                memset(slack,0x7f,sizeof(slack[0])*n);             //松驰值初始化无穷大
                if(DFS(i)==1)                                 //有增广路则break,否则修改顶标值
                    break;
                mn=INF;
                for(j=0;j<n;j++)
                    if(vsty[j]==0) mn=Min(mn,slack[j]);         //求最小的松弛值
                for(j=0;j<n;j++){
                    if(vstx[j]==1) lx[j]-=mn;                   //交错子树中X中的顶标-mn
                    if(vsty[j]==1) ly[j]+=mn;                   //交错子树中Y中的顶标+mn
                    if(vsty[j]==0) slack[j]-=mn;                //非交错子树中的Y的顶点松驰值-mn
                }
            }
        }
        sum=0;
        for(i=0;i<n;i++)
            sum+=lx[i]+ly[i];//加上所有顶标值
        return sum;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        long i,j;
        while(scanf("%ld",&n)!=EOF){
            memset(ly,0,sizeof(ly[0])*n);
            for(i=0;i<n;i++){
                for(j=0;j<n;j++){
                    scanf("%ld",&edge[i][j]);
                    if(lx[i]<edge[i][j])
                        lx[i]=edge[i][j];
                }
            }
            printf("%ld\n",KM());
        }
        return 0;
    }


  • 相关阅读:
    python cookbook 笔记二
    python cookbook 笔记一
    aircrack-ng笔记
    TeamCity 和 Nexus 的使用
    Linux 搭建 nexus 私服【转】
    maven阿里云镜像
    kali linux 破解wpa密码
    python正则表达式二[转]
    Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
    集合解析
  • 原文地址:https://www.cnblogs.com/yyf573462811/p/6365148.html
Copyright © 2011-2022 走看看