• hoj 2739 中国邮局问题


      1 /*若原图的基图不连通,
      2 或者存在某个点的入度或出度为 0 则无解。
      3 统计所有点的入度出度之差 Di, 对于 Di > 0 的点,
      4 加边(s, i, Di, 0); 对于 Di < 0 的点加边(i, t, -Di,0);
      5 对原图中的每条边(i, j),
      6 在网络中加边(i, j, ∞, Dij),Dij 为边(i, j)的权值。
      7 求一次最小费用流,费用加上原图所有边权和即为结果。
      8 若进一步要求输出最小权值回路,则对所有流量 fij > 0 的边(i, j),在原图中复制fij 份,这样原图便成为欧拉图,求一次欧拉回路即可。
      9 */
     10 #include <iostream>
     11 #include <cstdio>
     12 #include <cstring>
     13 #include <queue>
     14 #include <algorithm>
     15 #include <cmath>
     16 
     17 using namespace std;
     18 
     19 const int maxn = 1e2 + 5;
     20 const int maxm = 2e4 + 5;
     21 const int inf = 0x3f3f3f3f;
     22 
     23 struct MCMF {
     24     struct Edge {
     25         int v, c, w, next;
     26     }p[maxm << 1];
     27     int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
     28     bool vis[maxn];
     29     void init(int nt){
     30         e = 0, n = nt + 1;
     31         memset(head, -1, sizeof(head[0]) * (n + 2));
     32     }
     33     void addEdge(int u, int v, int c, int w){
     34         p[e].v = v; p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
     35         swap(u, v);
     36         p[e].v = v; p[e].c = 0; p[e].w = -w; p[e].next = head[u]; head[u] = e++;
     37     }
     38     bool spfa(int S, int T){
     39         queue <int> q;
     40         for (int i = 0; i <= n; ++i)
     41             vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;
     42         vis[S] = 1; dis[S] = 0;
     43         q.push(S);
     44         while (!q.empty()){
     45             int u = q.front(); q.pop();
     46             vis[u] = 0;
     47             for (int i = head[u]; i + 1; i = p[i].next){
     48                 int v = p[i].v;
     49                 if (p[i].c && dis[v] > dis[u] + p[i].w){
     50                     dis[v] = dis[u] + p[i].w;
     51                     pre[v] = i;
     52                     if (!vis[v]){
     53                         q.push(v);
     54                         vis[v] = 1;
     55                         if (++cnt[v] > n) return 0;
     56                     }
     57                 }
     58             }
     59         }
     60         return dis[T] != inf;
     61     }
     62     int mcmf(int S, int T){
     63         sumFlow = 0;
     64         int minFlow = 0, minCost = 0;
     65         while (spfa(S, T)){
     66             minFlow = inf + 1;
     67             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
     68                 minFlow = min(minFlow, p[i].c);
     69             sumFlow += minFlow;
     70             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ]){
     71                 p[i].c -= minFlow;
     72                 p[i ^ 1].c += minFlow;
     73             }
     74             minCost += dis[T] * minFlow;
     75         }
     76         return minCost;
     77     }
     78     int ind[maxn], outd[maxn], ans ;
     79     bool build(int nt, int mt){
     80         init(nt);
     81         memset(ind, 0, sizeof(ind));
     82         memset(outd, 0, sizeof(outd));
     83         ans = 0;
     84         int u, v, c;
     85         while (mt--){
     86             scanf("%d%d%d", &u, &v, &c);
     87             u++, v++;
     88             addEdge(u, v, inf, c);
     89             ans += c;
     90             outd[u]++, ind[v]++;
     91         }
     92         for (int i = 1; i <= nt; ++i){
     93             if (ind[i] == 0 || outd[i] == 0) return false;
     94         }
     95         for (int i = 1; i <= nt; ++i){
     96             if (ind[i] - outd[i] > 0)
     97                 addEdge(0, i, ind[i] - outd[i], 0);
     98             else if (ind[i] - outd[i] < 0) 
     99                 addEdge(i, n, outd[i] - ind[i], 0);
    100         }
    101         return true;
    102     }
    103     void solve(){
    104         ans += mcmf(0, n);
    105         printf("%d
    ", ans);
    106     }
    107 }my;
    108 int main(){
    109     int tcase, n, m;
    110     scanf("%d", &tcase);
    111     while (tcase--){
    112         scanf("%d%d", &n, &m);
    113         if (!my.build(n, m)){
    114             printf("-1
    ");
    115             continue;
    116         }
    117         my.solve();
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    GraphQL:Descriptor Attributes
    C++ 条件变量
    C++ future
    C++ 互斥
    C++ 通用锁管理
    并发
    C++ 线程
    智能指针
    PMP4.项目整合管理4.7结束项目或阶段
    PMP4.项目整合管理4.5监控项目工作
  • 原文地址:https://www.cnblogs.com/Missa/p/3273552.html
Copyright © 2020-2023  润新知