• hdu 1853 (费用流 拆点)


    // 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。 

    思路:原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从 u' 引相同性质的边到汇点,若原图中存在 (u, v) ,则从 u 引容量为 1 费用为 c(u, v) 的边到 v' 。

    其实这里的源模拟的是出度,汇模拟的是入度,因为环中每个点的出度等于入度等于 1 ,那么如果最大流不等于顶点数 n ,则无解;否则,答案就是最小费用。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <queue>
      5 
      6 using namespace std;
      7 
      8 const int maxn = 2e2 + 5;
      9 const int maxm = 2e4 + 5;
     10 const int inf = 0x3f3f3f3f;
     11 
     12 struct MCMF
     13 {
     14     struct Edge
     15     {
     16         int v, c, w, next;
     17     }p[maxm << 1];
     18     int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
     19     bool vis[maxn];
     20     void init(int nt)
     21     {
     22         e = 0, n = nt;
     23         memset(head, -1, sizeof(head[0]) * (n + 2) );
     24     }
     25     void addEdge(int u, int v, int c, int w)
     26     {
     27         p[e].v = v, p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
     28         swap(u, v);
     29         p[e].v = v, p[e].c = 0; p[e].w = -w; p[e].next = head[u]; head[u] = e++;
     30     }
     31     bool spfa(int S, int T)
     32     {
     33         queue <int> q;
     34         for (int i = 0; i <= n; ++i)
     35             vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;
     36         vis[S] = 1, dis[S] = 0;
     37         q.push(S);
     38         while (!q.empty())
     39         {
     40             int u = q.front(); q.pop();
     41             vis[u] = 0;
     42             for (int i = head[u]; i + 1; i = p[i].next)
     43             {
     44                 int v = p[i].v;
     45                 if (p[i].c && dis[v] > dis[u] + p[i].w)
     46                 {
     47                     dis[v] = dis[u] + p[i].w;
     48                     pre[v] = i;
     49                     if (!vis[v])
     50                     {
     51                         q.push(v);
     52                         vis[v] = 1;
     53                         if (++cnt[v] > n) return 0;
     54                     }
     55                 }
     56             }
     57         }
     58         return dis[T] != inf;
     59     }
     60     int mcmf(int S, int T)
     61     {
     62         sumFlow = 0;
     63         int minFlow = 0, minCost = 0;
     64         while (spfa(S, T))
     65         {
     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             {
     72                 p[i].c -= minFlow;
     73                 p[i ^ 1].c += minFlow;
     74             }
     75             minCost += dis[T] * minFlow;
     76         }
     77         return minCost;
     78     }
     79     void build(int nt, int mt)
     80     {
     81         init((nt << 1) + 1);
     82         int u, v, c;
     83         for (int i = 1; i <= nt; ++i)
     84         {
     85             addEdge(0, i, 1, 0);
     86             addEdge(i + nt, n, 1, 0);
     87         }
     88         while (mt--)
     89         {
     90             scanf("%d%d%d", &u, &v, &c);
     91             addEdge(u, v + nt, 1, c);
     92         }
     93     }
     94     void solve(int nt)
     95     {
     96         int ans = mcmf(0, n);
     97         if ( sumFlow != nt)
     98             printf("-1
    ");
     99         else
    100             printf("%d
    ", ans);
    101     }
    102 }my;
    103 
    104 int main()
    105 {
    106     int n, m;
    107     while (~scanf("%d%d", &n, &m))
    108     {
    109         my.build(n, m);
    110         my.solve(n);
    111     }
    112     return 0;
    113 }
  • 相关阅读:
    每日一个设计模式之策略模式
    Java发送get和post请求
    sql分组取最大值
    解析xml
    jsp:include
    schema的详解2
    文法和语言
    高级语言程序简介
    Dataframe根据某一列的值获取满足条件的行的其他列的值
    Dataframe数值转为二维列表
  • 原文地址:https://www.cnblogs.com/Missa/p/3265691.html
Copyright © 2020-2023  润新知