• 二分图匹配问题


    二分图最大匹配

    二分图最大权匹配

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int LEN = 1e3 + 5;
     4 typedef long long ll;
     5 int n, n1, n2, m;
     6 const int oo = 1e9;
     7 ll ans;
     8 namespace KM {
     9     int qh, qt;
    10     int w[LEN][LEN], q[LEN];
    11     int lx[LEN], ly[LEN], pre[LEN], slk[LEN], nxt[LEN], vx[LEN], mat[LEN], vy[LEN];
    12     void match(int &u) {
    13         while (u) {
    14             nxt[u] = pre[u];
    15             swap(u, mat[pre[u]]);
    16         }
    17     }
    18     void bfs(int s) {
    19         qh = qt = 0;
    20         vx[q[++qt] = s] = 1;
    21         while (1) {
    22             while (qh < qt) {
    23                 int u = q[++qh];
    24                 for (int v = 1; v <= n; v++) {
    25                     int tmp;
    26                     if (vy[v] || (tmp = lx[u] + ly[v] - w[u][v]) > slk[v]) continue;
    27                     pre[v] = u;
    28                     if (!tmp) {
    29                         if (!nxt[v]) return match(v);
    30                         vy[v] = vx[q[++qt] = nxt[v]] = 1;
    31                     } else slk[v] = tmp;
    32                 }
    33             }
    34             int a = oo;
    35             for (int i = 1; i <= n; i++) {
    36                 if (!vy[i] && a > slk[i]) a = slk[s = i];           
    37             }
    38             for (int i = 1; i <= n; i++) {
    39                 if (vx[i]) lx[i] -= a;
    40                 if (vy[i]) ly[i] += a;
    41                 else slk[i] -= a;
    42             }
    43             if (!nxt[s]) return match(s);
    44             vy[s] = vx[q[++qt] = nxt[s]] = 1;
    45         }
    46     }
    47     void km() {
    48         for (int i = 1; i <= n; i++) {
    49             for (int j = 1; j <= n; j++) {
    50                 slk[j] = oo;
    51                 vx[j] = vy[j] = 0;
    52                 lx[i] = max(lx[i], w[i][j]);
    53             }
    54             bfs(i);
    55         }
    56         ans = 0;
    57         for (int i = 1; i <= n; i++) ans += lx[i] + ly[i];
    58         printf("%lld
    ", ans);
    59         for (int i = 1; i < n1; i++) {
    60             printf("%d ", w[i][mat[i]] ? mat[i] : 0);
    61         }
    62         printf("%d
    ", w[n1][mat[n1]] ? mat[n1] : 0);
    63     }
    64 }
    65 using namespace KM;
    66 int main() {
    67     scanf("%d %d %d", &n1, &n2, &m);
    68     n = max(n1, n2);//左右的点的编号都是从1开始,n为较大的值
    69     for (int i = 1; i <= m; i++) {
    70         int x, y, z;//表示的是左边的第x个点和右边的第y个点可以花费z匹配
    71         scanf("%d %d %d", &x, &y, &z);
    72         w[x][y] = max(w[x][y], z);
    73     }
    74     km();
    75     return 0;
    76 }
    KM
  • 相关阅读:
    2016某天闲谈
    APP测试入门篇之APP基础知识(001)
    windows服务器下frp实现内网穿透
    nginx使用与配置
    spring boot 实现优雅的关闭
    spring boot 自定义sql分页查询
    java获取类加载路径和项目根路径的5种方法
    linux下 启动node 和关闭node
    docker 安装 fastdfs
    docker 常用命令和常用容器启动
  • 原文地址:https://www.cnblogs.com/NineSwords/p/9470183.html
Copyright © 2020-2023  润新知