POJ 2135 【最小费用最大流】.cpp

题意:

给出m个路径的起点和终点还有长度

找出一条路径可以从1到n然后回到1..

并保证找到的路径是不重复而且是最短的..

 

思路:

容量控制经过只有1次

费用控制长度

在建完图后求最小费用最大流..

就可以找出最短距离..而且没有重复路径..

 

Tips:

※ 0点作为超级源点和1相连   n+1作为超级汇点和n相连    然后容量为2费用为0 保证一进一出

※ 建图的时候..相邻的正反边要紧挨着写..

  因为更改图中的容量的时候..

    edge[load[u]].c -= mn;

        edge[load[u]^1].c += mn;

    位运算表示的是反向边..所以加的时候应该紧挨着加..

※ 加边的时候..除了加已知的边 还要加入反向边 同时要加入容量为0 费用为负值的边..

  所以每次运算的时候..应该先加入一条正向边 然后加入正向边的反向负值边

            然后加入一条反向边 再加入反向边的反向负值边

 

Code:

 

View Code
  1 #include <stdio.h>

  2 #include <cstring>

  3 #include <algorithm>

  4 using namespace std;

  5 #define clr(x) memset(x, 0, sizeof(x))

  6 const int INF = 0x1f1f1f1f;

  7 const int MAXN = 1010;

  8 const int MAXM = 100010;

  9 struct Edge

 10 {

 11     int to;

 12     int next;

 13     int c;

 14     int f;

 15 }edge[MAXM];

 16 int head[MAXN];

 17 int tot;

 18 int n;

 19 int dis[MAXN], load[MAXN], p[MAXN];

 20 bool flag[MAXN];

 21 

 22 void add(int s, int u, int c, int f)

 23 {

 24     edge[tot].to = u;

 25     edge[tot].next = head[s];

 26     edge[tot].f = f;

 27     edge[tot].c = c;

 28     head[s] = tot++;

 29 }

 30 

 31 bool spfa(int s, int en)

 32 {

 33     int que[MAXN*10], qout, qin;

 34     clr(flag);

 35     memset(p, 0xff, sizeof(p));

 36     memset(load, 0xff, sizeof(load));

 37     memset(dis, INF, sizeof(dis));

 38     qin = qout = 0;

 39     que[qin++] = s;

 40     dis[s] = 0;

 41     flag[s] = true;

 42     while(qin != qout) {

 43         int e = que[qout++];

 44         flag[e] = false;

 45         for(int i = head[e]; i != -1; i=edge[i].next) {

 46             if(edge[i].c) {

 47                 int ne = edge[i].to;

 48                 if(dis[ne]-dis[e] > edge[i].f) {

 49                     dis[ne] = dis[e]+edge[i].f;

 50                     p[ne] = e;

 51                     load[ne] = i;

 52                     if(!flag[ne]) {

 53                         flag[ne] = true;

 54                         que[qin++] = ne;

 55                     }

 56                 }

 57             }

 58         }

 59     }

 60     if(dis[en] == INF)

 61         return false;

 62     else return true;

 63 }

 64 

 65 int min_c_f(int s, int e)

 66 {

 67     int u, mn;

 68     int ans_f = 0, ans_c = 0;

 69     while(spfa(s, e))

 70     {

 71         u = e;

 72         mn = INF;

 73         while(p[u] != -1) {

 74             mn = min(edge[load[u]].c, mn);

 75             u = p[u];

 76         }

 77         u = e;

 78         while(p[u] != -1) {

 79             edge[load[u]].c -= mn;

 80             edge[load[u]^1].c += mn;

 81             u = p[u];

 82         }

 83         ans_f += dis[e]*mn;

 84         ans_c += mn;

 85     }

 86     return ans_f;

 87 }

 88 

 89 int main()

 90 {

 91     int i, j, k;

 92     int m;

 93     int a, b, l;

 94     while(scanf("%d %d", &n, &m) != EOF)

 95     {

 96         clr(load), clr(dis), clr(p);

 97         memset(head, 0xff, sizeof(head));

 98         tot = 0;

 99 

100         while(m--) {

101             scanf("%d %d %d", &a, &b, &l);

102             add(a, b, 1, l);

103             add(b, a, 0, -l);

104             add(b, a, 1, l);

105             add(a, b, 0, -l);

106         }

107 

108         add(0, 1, 2, 0);

109         add(1, 0, 2, 0);

110         add(n, n + 1, 2, 0);

111         add(n+1, n , 2, 0);

112         int ans = min_c_f(0, n+1);

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

114     }

115     return 0;

116 }

 

 

 

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

你可能感兴趣的:(poj)