zoukankan      html  css  js  c++  java
  • UVA11383 Golden Tiger Claw(KM算法)

    刘汝佳新书---训练指南

    题意:给定一个N*N矩阵,每个格子里都有一个正整数w[i][j]。你的任务是给每行确定一个整数row[i],每列确定一个整数col[i],使得对于任意格子(i,j),w[i][j]《=row[i]+col[j]。所有row[i]和col[i]之和应尽量小。

    分析:这题是KM算法的一个副产品,KM算法有等式l(x)+l(y)>=w(x,y).

    // File Name: 11383.cpp
    // Author: zlbing
    // Created Time: 2013/2/27 23:37:40
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define MAXN 500+5
    int Left[MAXN];
    int w[MAXN][MAXN];
    int Lx[MAXN],Ly[MAXN];
    bool S[MAXN],T[MAXN];
    int N;
    bool match(int i)
    {
        S[i]=true;
        for(int j=1;j<=N;j++)if(Lx[i]+Ly[j]==w[i][j]&&!T[j])
        {
            T[j]=true;
            if(Left[j]==0||match(Left[j]))
            {
                Left[j]=i;
                return true;
            }
        }
        return false;
    }
    void update(){
        int a=INF;
        for(int i=1;i<=N;i++)if(S[i])
            for(int j=1;j<=N;j++)if(!T[j])
                a=min(a,Lx[i]+Ly[j]-w[i][j]);
        for(int i=1;i<=N;i++){
            if(S[i])Lx[i]-=a;
            if(T[i])Ly[i]+=a;
        }
    }
    void KM()
    {
        for(int i=1;i<=N;i++){
            Left[i]=Lx[i]=Ly[i]=0;
            for(int j=1;j<=N;j++)
            {
                Lx[i]=max(Lx[i],w[i][j]);
            }
        }
        for(int i=1;i<=N;i++){
            for(;;){
                CL(S,0);
                CL(T,0);
                if(match(i))break;
                else update();
            }
        }
    }
    
    int main(){
        while(~scanf("%d",&N))    
        {
            for(int i=1;i<=N;i++)
                for(int j=1;j<=N;j++)
                    scanf("%d",&w[i][j]);
            KM();
            for(int i=1;i<=N;i++)
                if(i==1)printf("%d",Lx[i]);
                else printf(" %d",Lx[i]);
            printf("\n");
            for(int i=1;i<=N;i++)
                if(i==1)printf("%d",Ly[i]);
                else printf(" %d",Ly[i]);
            printf("\n");
            int sum=0;
            for(int i=1;i<=N;i++)
                sum+=Lx[i]+Ly[i];
            printf("%d\n",sum);
    
        }
        return 0;
    }
  • 相关阅读:
    (五)SpringCloud学习系列-构建部门微服务消费者Module
    (四)SpringCloud学习系列-构建部门微服务提供者Module
    (三)SpringCloud学习系列-Rest微服务构建
    git提交 显示作者名不是自己
    linux一些常见命令
    支付宝退款demo
    ffmpeg截取视频
    excel导入数据到mysql
    二分法与冒泡排序
    mysql的级联删除
  • 原文地址:https://www.cnblogs.com/arbitrary/p/2936063.html
Copyright © 2011-2022 走看看