• HDU2255奔小康赚大钱-完全带权二分图最佳匹配


    这题一打眼是最大费用最大流,但是边太多(完全二分图),会被卡掉。

    正解:KM算法

    一个不错的博客,但是有些东西还是不是很明白。

    http://blog.sina.com.cn/s/blog_691ce2b701016reh.html

    关于他写的最后一句,每次要更新stack,实测本题不需要,可能别的地方会用到,以后再讨论。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define inf 0x3f3f3f3f
     6 using namespace std;
     7 int dis[303][303];
     8 int lx[333],ly[333];
     9 int mind[333];
    10 int visx[333];
    11 int visy[333];
    12 int match[333];
    13 int N;
    14 bool dfs(int u)
    15 {
    16     visx[u] = 1;
    17     for (int i = 1; i<= N; i++)
    18     {
    19         if (visy[i]) continue;
    20         int t = lx[u] + ly[i] - dis[u][i];
    21         if (t == 0)
    22         {
    23             visy[i] = 1;
    24             if (match[i]==-1 || dfs(match[i]))
    25             {
    26                 match[i] = u;
    27                 return true;
    28             }
    29         }
    30         else if (mind[i] > t)
    31         {
    32             mind[i] = t;
    33         }
    34     }
    35     return false;
    36 }
    37 int KM()
    38 {
    39     memset(ly,0,sizeof(lx));
    40     memset(match,-1,sizeof(match));
    41     //枚举一方面的点
    42     for (int i = 1 ;i<=N; i++)
    43     {   //储存最小的mind
    44         memset(mind,inf,sizeof(mind));
    45         memset(visx,0,sizeof(visx));
    46         memset(visy,0,sizeof(visy));
    47         while (!dfs(i)) //这里需要多次dfs同一个点,因为更改lx和ly会使得需要再次dfs
    48         {
    49             int d = inf;
    50             for (int j = 1 ; j<=N; j++)
    51             {
    52                 if (!visy[j]) d = min(d,mind[j]);
    53             }
    54             for (int j = 1; j<=N; j++)
    55             {
    56                 if (visx[j]) lx[j]-=d;
    57                 if (visy[j]) ly[j]+=d;
    58             }
    59             memset(visx,0,sizeof(visx));
    60             memset(visy,0,sizeof(visy));
    61         }
    62     }
    63     int ans = 0;
    64     for (int i= 1;i<= N;i++)
    65             ans += dis[match[i]][i];
    66     return ans;
    67 }
    68 int main()
    69 {
    70     while (scanf ("%d",&N)!=EOF)
    71     {
    72         for (int i = 1; i<=N;i++)
    73         lx[i] = -inf;
    74         for (int i = 1 ; i<= N; i++)
    75         {
    76             for (int j = 1; j <= N; j++)
    77             {
    78                 scanf("%d",&dis[i][j]);
    79                 lx[i] = max(lx[i],dis[i][j]);
    80             }
    81         }
    82         printf ("%d
    ",KM());
    83     }
    84 }
  • 相关阅读:
    怎样把顶级控件加在另一个控件上?
    GML规范相关资源
    VB6.0的事件、回调函数等
    [转]使用ErrorProvider改善用户体验
    今日新增3D词汇
    [转]在用数据绑定的时候我为什么不能把焦点移出(Tab out)我的控件?(译)
    [翻译]Windows Phone 7 Application Controls
    转帖Windows Phone 7开发环境搭建
    利用SDF2.3获取Windows Mobile上的IP地址和MAC地址
    “2010 GCR MVP Open Day”之行
  • 原文地址:https://www.cnblogs.com/HITLJR/p/5979229.html
Copyright © 2020-2023  润新知