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\n");

 99         else

100             printf("%d\n", 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 }

 

你可能感兴趣的:(HDU)