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
  • 相关阅读:
    【Others】2048逻辑整理
    【MySQL】MySQL学习笔记(一)
    【PHP】对TP中session的理解
    【Python基础】python 作用域
    【phantomJs + selenium】动态cookie,数据采集记录
    [ZJOI2015][LOJ2137]诸神眷顾的幻想乡(广义SAM)
    [CF235C]Cyclical Quest(SAM)
    [BZOJ1426]收集邮票(概率期望dp)
    [HDU5421]Victor and String(PAM)
    [CF932G]Palindrome Partition(PAM回文划分dp)
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12870538.html
Copyright © 2011-2022 走看看