zoukankan      html  css  js  c++  java
  • [POJ2195]Going Home(带权最大匹配,KM,最小费用流)

    题目链接:http://poj.org/problem?id=2195

    题意:给个图,m代表人H代表房子。每一个m要有一个H,代价是曼哈顿距离。问让所有m找到房子的最小花费。

    可以直接枚举m和H建二分图跑KM。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <iomanip>
      4 #include <cstring>
      5 #include <climits>
      6 #include <complex>
      7 #include <cassert>
      8 #include <cstdio>
      9 #include <bitset>
     10 #include <vector>
     11 #include <deque>
     12 #include <queue>
     13 #include <stack>
     14 #include <ctime>
     15 #include <set>
     16 #include <map>
     17 #include <cmath>
     18 
     19 using namespace std;
     20 
     21 const int maxn = 310;
     22 const int inf = 0x3f3f3f3f;
     23 int nx,ny;
     24 int G[maxn][maxn];
     25 int linker[maxn],lx[maxn],ly[maxn];
     26 int slack[maxn];
     27 bool visx[maxn],visy[maxn];
     28 
     29 bool dfs(int x) {
     30     visx[x] = true;
     31     for(int y = 0; y < ny; y++) {
     32         if(visy[y])continue;
     33         int tmp = lx[x] + ly[y] - G[x][y];
     34         if(tmp == 0) {
     35             visy[y] = true;
     36             if(linker[y] == -1 || dfs(linker[y])) {
     37                 linker[y] = x;
     38                 return true;
     39             }
     40         }
     41         else if(slack[y] > tmp)
     42             slack[y] = tmp;
     43     }
     44     return false;
     45 }
     46 int km() {
     47     memset(linker,-1,sizeof(linker));
     48     memset(ly,0,sizeof(ly));
     49     for(int i = 0;i < nx;i++) {
     50         lx[i] = -inf;
     51         for(int j = 0;j < ny;j++)
     52             if(G[i][j] > lx[i])
     53                 lx[i] = G[i][j];
     54     }
     55     for(int x = 0;x < nx;x++) {
     56         for(int i = 0;i < ny;i++)
     57             slack[i] = inf;
     58         while(true) {
     59             memset(visx,false,sizeof(visx));
     60             memset(visy,false,sizeof(visy));
     61             if(dfs(x))break;
     62             int d = inf;
     63             for(int i = 0;i < ny;i++)
     64                 if(!visy[i] && d > slack[i])
     65                     d = slack[i];
     66             for(int i = 0;i < nx;i++)
     67                 if(visx[i])
     68                     lx[i] -= d;
     69             for(int i = 0;i < ny;i++) {
     70                 if(visy[i])ly[i] += d;
     71                 else slack[i] -= d;
     72             }
     73         }
     74     }
     75     int res = 0;
     76     for(int i = 0;i < ny;i++)
     77         if(linker[i] != -1)
     78             res += G[linker[i]][i];
     79     return res;
     80 }
     81 
     82 typedef pair<int,int> pii;
     83 char mp[maxn][maxn];
     84 int n, m;
     85 vector<pii> h, p;
     86 
     87 int main() {
     88   // freopen("in", "r", stdin);
     89     while(~scanf("%d%d",&n,&m) && n+m) {
     90         memset(mp, 0, sizeof(mp));
     91         h.clear(); p.clear();
     92         for(int i = 1; i <= n; i++) {
     93             scanf("%s", mp[i]+1);
     94         }
     95         for(int i = 1; i <= n; i++) {
     96             for(int j = 1; j <= m; j++) {
     97                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
     98                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
     99             }
    100         }
    101         memset(G, 0, sizeof(G));
    102         nx = h.size(); ny = p.size();
    103         for(int i = 0; i < h.size(); i++) {
    104             for(int j = 0; j < p.size(); j++) {
    105                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
    106                 G[i][j] = -dis;
    107             }
    108         }
    109         printf("%d
    ", -km());
    110     }
    111     return 0;
    112 }
    KM

    也可以用最小费用流建模。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <iomanip>
      4 #include <cstring>
      5 #include <climits>
      6 #include <complex>
      7 #include <cassert>
      8 #include <cstdio>
      9 #include <bitset>
     10 #include <vector>
     11 #include <deque>
     12 #include <queue>
     13 #include <stack>
     14 #include <ctime>
     15 #include <set>
     16 #include <map>
     17 #include <cmath>
     18 
     19 using namespace std;
     20 
     21 typedef long long LL;
     22 typedef struct Node {
     23     int u, v, next;
     24     LL c, w;
     25 }Node;
     26 const int maxn = 20010;
     27 const int maxm = 40010;
     28 const LL mod = 0x3f3f3f3fLL;
     29 const LL inf = (1LL<<55);
     30 int tot, head[maxn];
     31 LL dist[maxn];
     32 LL cost, flow;
     33 Node e[maxm];
     34 int pre[maxn];
     35 bool visit[maxn];
     36 queue<int> Q;
     37 int S, T, N;
     38 
     39 void init() {
     40     S = T = N = 0;
     41     memset(head, -1, sizeof(head));
     42     tot = 0;
     43 }
     44 
     45 void adde(int u, int v, LL c, LL w) {
     46     e[tot].u = u; e[tot].v = v; e[tot].c = c; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
     47     e[tot].u = v; e[tot].v = u; e[tot].c = 0; e[tot].w = -w; e[tot].next = head[v]; head[v] = tot++;
     48 }
     49 bool spfa(int s, int t, int n) {
     50     int i;
     51     for(i = 0; i <= n; i++) {
     52         dist[i] = inf;
     53         visit[i] = 0;
     54         pre[i] = -1;
     55     }
     56     while(!Q.empty()) Q.pop();
     57     Q.push(s);
     58     visit[s] = true;
     59     dist[s] = 0;
     60     pre[s] = -1;
     61     while(!Q.empty()) {
     62         int u = Q.front();
     63         visit[u] = false;
     64         Q.pop();
     65         for(int j = head[u]; j != -1; j = e[j].next) {
     66             if(e[j].c > 0 && dist[u] + e[j].w < dist[e[j].v]) {
     67                 dist[e[j].v] = dist[u] + e[j].w;
     68                 pre[e[j].v] = j;
     69                 if(!visit[e[j].v]) {
     70                     Q.push(e[j].v);
     71                     visit[e[j].v] = true;
     72                 }
     73             }
     74         }
     75     }
     76     if(dist[t] == inf) return false;
     77     else return true;
     78 }
     79 LL ChangeFlow(int t) {
     80     LL det = mod;
     81     int u = t;
     82     while(~pre[u]) {
     83         u = pre[u];
     84         det = min(det, e[u].c);
     85         u = e[u].u;
     86     }
     87     u = t;
     88     while(~pre[u]) {
     89         u = pre[u];
     90         e[u].c -= det;
     91         e[u ^ 1].c += det;
     92         u = e[u].u;
     93     }
     94     return det;
     95 }
     96 LL MinCostFlow(int s, int t, int n) {
     97     LL mincost, maxflow;
     98     mincost = maxflow = 0;
     99     while(spfa(s, t, n)) {
    100         LL det = ChangeFlow(t);
    101         mincost += det * dist[t];
    102         maxflow += det;
    103     }
    104     cost = mincost;
    105     flow = maxflow;
    106     return mincost;
    107 }
    108 
    109 typedef pair<int,int> pii;
    110 char mp[111][111];
    111 int n, m;
    112 vector<pii> h, p;
    113 
    114 int main() {
    115   // freopen("in", "r", stdin);
    116     while(~scanf("%d%d",&n,&m) && n+m) {
    117         init();
    118         memset(mp, 0, sizeof(mp));
    119         h.clear(); p.clear();
    120         for(int i = 1; i <= n; i++) {
    121             scanf("%s", mp[i]+1);
    122         }
    123         for(int i = 1; i <= n; i++) {
    124             for(int j = 1; j <= m; j++) {
    125                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
    126                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
    127             }
    128         }
    129         S = 0, T = h.size() + p.size() + 1, N = T + 1;
    130         for(int i = 0; i < h.size(); i++) adde(S, i+1, 1, 0);
    131         for(int i = 0; i < p.size(); i++) adde(h.size()+i+1, T, 1, 0);
    132         for(int i = 0; i < h.size(); i++) {
    133             for(int j = 0; j < p.size(); j++) {
    134                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
    135                 int hi = i + 1;
    136                 int pi = h.size() + j + 1;
    137                 adde(hi, pi, 1, (LL)dis);
    138             }
    139         }
    140         cout << MinCostFlow(S, T, N) << endl;
    141     }
    142     return 0;
    143 }
  • 相关阅读:
    JS--XML 操作
    JS--中的 Cookie 与存储
    php qr生成二维码
    jQuery cookie插件保存用户登陆信息
    linux BASH shell设置字体与背景颜色
    linux iostat命令详解 磁盘操作监控工具
    Nginx下10个安全问题提示
    PHP计算某个目录大小的方法
    php验证是否是md5编码的代码
    JS正则表达式获取字符串中特定字符
  • 原文地址:https://www.cnblogs.com/kirai/p/6769135.html
Copyright © 2011-2022 走看看