zoukankan      html  css  js  c++  java
  • hdu_2255_奔小康赚大钱(KM带权二分匹配板子)

    题目连接:hdu_2255_奔小康赚大钱

    存个板子

     1 /*
     2 其实在求最大 最小的时候只要用一个模板就行了,
     3 把边的权值去相反数即可得到另外一个.求结果的时候再去
     4 相反数即可,最大最小有一些地方不同。。
     5 */
     6 #include <iostream>
     7 #include<cstring>
     8 #include<cstdio>
     9 #include<cmath>
    10 const int N = 301;
    11 const int INF = (1<<30)-1;
    12 int w[N][N];
    13 int lx[N],ly[N]; //顶标
    14 int linky[N],visx[N],visy[N],slack[N];
    15 int n;
    16 bool find(int x){
    17     visx[x]=1;
    18     for(int y=1;y<=n;y++){
    19         if(visy[y])continue;          
    20         int t=lx[x]+ly[y]-w[x][y];
    21         if(t==0){
    22             visy[y] = 1;
    23             if(linky[y]==-1||find(linky[y]))return linky[y]=x,1;
    24         }
    25         else if(slack[y]>t)slack[y]=t;    
    26     }
    27     return 0;
    28 }
    29 
    30 int KM(){
    31     int i,j;
    32     memset(linky,-1,sizeof(linky));
    33     memset(ly,0,sizeof(ly));
    34     for(i=1;i<=n;i++){
    35         lx[i]=-INF;
    36          for(j = 1;j<=n;j++)
    37             if(w[i][j]>lx[i])lx[i]=w[i][j];    
    38     }
    39     for(int x=1;x<=n;x++){
    40         for(i=1;i<=n;i++)slack[i]=INF;
    41         while(1){
    42             memset(visx,0,sizeof(visx));
    43             memset(visy,0,sizeof(visy));
    44             if(find(x))break;//找到增广轨,退出    
    45             int d=INF;
    46             for(i=1;i<=n;i++) //没找到,对l做调整(这会增加相等子图的边),重新找
    47             if(!visy[i]&&d>slack[i])d=slack[i];
    48             for(i=1;i<=n;i++)if(visx[i])lx[i]-=d;
    49             for(i=1;i<=n;i++)
    50                 if(visy[i])ly[i]+=d;else slack[i]-=d;  
    51         }
    52     }
    53     int result = 0;
    54     for(i=1;i<=n;i++)if(linky[i]>-1)result+=w[linky[i]][i];
    55     return result;
    56 }
    57 
    58 int main()
    59 {
    60     while(scanf("%d",&n)==1)
    61     {
    62         int cost;
    63         for(int i=1;i<=n;i++)
    64         for(int j=1;j<=n;j++)
    65         {
    66             scanf("%d",&cost);
    67             w[i][j]=cost;
    68         }
    69         printf("%d
    ",KM());
    70     }
    71     return 0;
    72 }
    View Code



  • 相关阅读:
    "Coding Interview Guide" -- 删除无序单链表中值重复出现的节点
    "Coding Interview Guide" -- 设计一个有getMin功能的栈
    "Coding Interview Guide" -- 仅用递归函数和栈操作逆序一个栈
    "Coding Interview Guide" -- 猫狗队列
    "Coding Interview Guide" -- 阶乘
    "Coding Interview Guide" -- 不用额外变量交换两个整数的值
    IDEA问题
    JAVA
    Log4j
    MAVEN教程
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5696081.html
Copyright © 2011-2022 走看看