hdu 3667 (拆边 mcmf)

注意题目中 边的容量 <= 5.可以把费用权值 a *f ^2化归成 a * f2, 即第一条边费用为 1 * a, 第二条 为 (4 - 1) * a, 第三条为 (9  - 4) * a。。。。。。

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <queue>

  5 

  6 using namespace std;

  7 

  8 const int maxn = 110;

  9 const int maxm = 25000;

 10 const int inf = 0x3f3f3f3f;

 11 const int ww[5] = {1, 3, 5, 7, 9};

 12 

 13 struct MCMF

 14 {

 15     struct Edge

 16     {

 17         int v, c, w, next;

 18     }p[maxm << 1];

 19     int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;

 20     bool vis[maxn];

 21     void init(int nt)

 22     {

 23         e = 0; n = nt;

 24         memset(head, -1, sizeof(head[0]) * (n + 2));

 25     }

 26     void addEdge(int u, int v, int c, int w)

 27     {

 28         p[e].v = v; p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;

 29         swap(u, v);

 30         p[e].v = v; p[e].c = 0; p[e].w =-w; p[e].next = head[u]; head[u] = e++;

 31     }

 32     bool spfa(int S, int T)

 33     {

 34         queue <int> q;

 35         for (int i = 0; i <= n; ++i)

 36             vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;

 37         vis[S] = 1; dis[S] = 0;

 38         q.push(S);

 39         while (!q.empty())

 40         {

 41             int u = q.front(); q.pop();

 42             vis[u] = 0;

 43             for (int i = head[u]; i + 1; i = p[i].next)

 44             {

 45                 int v = p[i].v;

 46                 if (p[i].c && dis[v] > dis[u] + p[i].w)

 47                 {

 48                     dis[v] = dis[u] + p[i].w;

 49                     pre[v] = i;

 50                     if (!vis[v])

 51                     {

 52                         q.push(v);

 53                         vis[v] = 1;

 54                         if (++cnt[v] > n) return 0;

 55                     }

 56                 }

 57             }

 58         }

 59         return dis[T] != inf;

 60     }

 61     int mcmf(int S, int T)

 62     {

 63         sumFlow = 0;

 64         int minFlow = 0, minCost = 0;

 65         while (spfa(S, T))

 66         {

 67             minFlow = inf + 1;

 68             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])

 69                 minFlow = min(minFlow, p[i].c);

 70             sumFlow += minFlow;

 71             for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])

 72                 p[i].c -= minFlow, p[i ^ 1].c += minFlow;

 73             minCost += dis[T] * minFlow;

 74         }

 75         return minCost;

 76     }

 77     void build(int nt, int mt, int kt)

 78     {

 79         init(nt);

 80         addEdge(0, 1, kt, 0);

 81         int u, v, c, w;

 82         for (int i = 0; i < mt; ++i)

 83         {

 84             scanf("%d%d%d%d", &u, &v, &w, &c);

 85             for (int j = 0; j < c; ++j)

 86                 addEdge(u, v, 1, w * ww[j]);

 87         }

 88     }

 89     void solve(int nt, int mt, int kt)

 90     {

 91         build(nt, mt, kt);

 92         int ans = mcmf(0, n);

 93     //    cout <<"sumFlow = "  << sumFlow << " cost = " << ans << endl;

 94         if (sumFlow != kt)

 95             printf("-1\n");

 96         else

 97             printf("%d\n", ans);

 98     }

 99 }my;

100 

101 int main()

102 {

103     int n, m, k;

104     while (~scanf("%d%d%d", &n, &m, &k))

105         my.solve(n, m, k);

106     return 0;

107 }

 

你可能感兴趣的:(HDU)