zoukankan      html  css  js  c++  java
  • UVA11383 Golden Tiger Claw

     

    题意:给你一个n*n的矩阵,让你给矩阵的每一行每一列附一个值,使得每一个矩阵中的点的行和列的值的和大于等于该点的权值,并使得行列值之和最小。

    思路:其实这道题我们就是跑一遍KM算法就行了,因为在KM过程中我们始终有两点之间的期望值之和大于等于两点之间的距离,我们就可以把期望值当做行列的值就行了,最终总和就是匹配完的图的所有行列的大小总和。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=505;
     6 const int Inf=0x3f3f3f3f;
     7 int val[N][N],q_heng[N],q_shu[N],vis_heng[N],vis_shu[N];
     8 int match[N],slack[N],n;
     9 bool dfs(int heng){
    10     vis_heng[heng]=1;
    11     for(int shu=1;shu<=n;++shu){
    12         if(vis_shu[shu]) continue;
    13         int gap=q_heng[heng]+q_shu[shu]-val[heng][shu];
    14         if(gap==0){
    15             vis_shu[shu]=true;
    16             if(match[shu]==-1||dfs(match[shu])){
    17                 match[shu]=heng;
    18                 return true;
    19             }
    20         }
    21         else{
    22                 slack[shu]=min(slack[shu],gap);
    23         }
    24     }
    25     return false;
    26 }
    27 void KM(){
    28     memset(match,-1,sizeof(match));
    29     memset(q_shu,0,sizeof(q_shu));
    30     for(int i=1;i<=n;++i){
    31         q_heng[i]=val[i][1];
    32         for(int j=2;j<=n;++j){
    33             q_heng[i]=max(q_heng[i],val[i][j]);
    34         }
    35     }
    36     for(int i=1;i<=n;++i){
    37         memset(slack,0x3f,sizeof(slack));
    38         while(true){
    39             memset(vis_heng,0,sizeof(vis_heng));
    40             memset(vis_shu,0,sizeof(vis_shu));
    41             if(dfs(i)) break;
    42             int d=Inf;
    43             for(int j=1;j<=n;++j)
    44                 if(!vis_shu[j]) d=min(d,slack[j]);
    45             for(int j=1;j<=n;++j){
    46                 if(vis_heng[j]) q_heng[j]-=d;
    47                 if(vis_shu[j]) q_shu[j]+=d;
    48                 else slack[j]-=d;
    49             }
    50         }
    51     }
    52 }
    53 int main(){
    54     while(scanf("%d",&n)==1){
    55         for(int i=1;i<=n;++i)
    56         for(int j=1;j<=n;++j)
    57             scanf("%d",&val[i][j]);
    58         KM();
    59         int ans=0;
    60         for(int i=1;i<=n;++i){
    61             printf("%d ",q_heng[i]);
    62             ans+=q_heng[i];
    63         }
    64         printf("
    ");
    65         for(int i=1;i<=n;++i){
    66             printf("%d ",q_shu[i]);
    67             ans+=q_shu[i];
    68         }
    69         printf("
    %d
    ",ans);
    70     }
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    换上 SansForgetica-Regular 字体,增加记忆能力
    Windows和Linux查看端口占用
    安卓打开远程调试(免root)
    debian系统解决包依赖问题的神器aptitude
    C# WinForm 实现窗体淡入淡出
    [图文教程]VS2017搭建opencv & C++ 开发环境
    C# 调用Tesseract实现OCR
    数据库工具链接阿里云MySQL数据库
    【转载】如何选择MySQL存储引擎
    java Long、Integer 、Double、Boolean类型 不能直接比较
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12870538.html
Copyright © 2011-2022 走看看