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

posted @ 2012-10-01 23:45  Griselda.  阅读(299)  评论(0编辑  收藏  举报