poj2135 最小费最大流

题目大意:N块田地M条道路。1为起点,N为终点,FJ从起点走到终点,经过不重复的路(可经过重复的点)再回到起点,求所花费最小时间。

 

建图要点:  1.要求路不重复,则使路的容量都为1.

       2.从起点到终点,再从终点到起点,故建立超级源点0超级汇点N+1,建路0-1,N-N+1容量都为2。

       3.有重边,所以要用邻接表。

       4.无向图,所以每条边都要建立正反两边。又因为一条路可能是从起点到终点时经过,也可能是从终点到起点时经过,所以还要建立反向的正反两边,一共4边。

       5.因为此题是无向图,所以建边的时候如果建两条费用都是正的边的话,退流时无法修正费用。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <string>
  8 #include <vector>
  9 #include <queue>
 10 #include <cmath>
 11 #include <stack>
 12 #include <map>
 13 #include <cmath>
 14 #include <set>
 15 #include <climits>
 16 #define INF 0x7fffffff
 17 #define finc(i,a,b) for(i=a;i<=b;i++)
 18 #define fdec(i,a,b) for(i=a;i>=b;i--)
 19 #define MAXN 10001
 20 #define MAXM 100002
 21 using namespace std;
 22 int N,M,Source,ans;
 23 struct E //使用数组模拟邻接表存储边信息
 24 {
 25     int b,cost,cap,next;
 26 }edge[MAXM];
 27 
 28 int list[MAXN],tot,p[MAXN],pre[MAXN],qe[MAXN];
 29 int dist[MAXN];
 30 queue<int>q;
 31 int cnt[MAXN];
 32 bool f[MAXN];
 33 
 34 void add(int a,int b,int cap,int cost) //构建邻接表
 35 {
 36 
 37     edge[tot].b=b;  edge[tot].cap=cap;  edge[tot].cost=cost;
 38     edge[tot].next=list[a];  list[a]=tot++;
 39     edge[tot].b=a;  edge[tot].cap=0;  edge[tot].cost=-cost;
 40     edge[tot].next=list[b];  list[b]=tot++;
 41 }
 42 void init()
 43 {
 44     cin>>N>>M;
 45     for(int i=1;i<=M;i++)
 46     {
 47         int a,b,cost;
 48         cin>>a>>b>>cost;
 49         add(a,b,1,cost);
 50         add(b,a,1,cost);
 51     }
 52 }
 53 
 54 bool spfa()                     //求最小费最短路
 55 {
 56     memset(f,0,sizeof(f));
 57     memset(pre,-1,sizeof(pre));
 58    // memset(cnt,0,sizeof(cnt));
 59     for(int i=1;i<=N+1;i++)    
 60     dist[i]=INF;
 61     dist[Source]=0;pre[0]=0;
 62     q.push(Source);f[Source]=0;
 63     while(q.size())
 64     {
 65         int a=q.front(),b;        
 66         q.pop();
 67         for(int k=list[a]; k!=-1; k=edge[k].next)    
 68         {
 69             b=edge[k].b;
 70             if(edge[k].cap&& dist[b]>dist[a]+edge[k].cost )
 71             {
 72                 dist[b]=dist[a]+edge[k].cost;
 73 
 74                 if(f[b] == 0)
 75                 {
 76                     f[b]=1;
 77                     q.push(b);
 78                 }
 79                 pre[b]=a;               ///记录前导后导,用于退流
 80                 qe[b]=k;
 81             }
 82         }
 83         f[a]=0;
 84     }
 85     if(pre[N+1] == -1) return false;
 86     else    return true;
 87 }
 88 void end()
 89 {
 90     int i,tmp=INF;
 91     for(i=N+1;i!=0;i=pre[i])
 92         tmp=min(tmp,edge[qe[i]].cap);
 93     ans+=dist[N+1]*tmp;                 ///单位费用乘流量
 94     for(i=N+1;i!=0;i=pre[i]){
 95         edge[qe[i]].cap-=tmp;
 96         edge[qe[i]^1].cap+=tmp;
 97     }
 98 }
 99 int main()
100 {
101     memset(list,-1,sizeof(list));
102     tot=0;ans=0; Source=0;
103     init();
104     add(0,1,2,0);
105     add(N,1+N,2,0);
106 
107 
108 
109     while(spfa()){
110         end();
111        // cout<<ans<<endl;
112     }
113     printf("%d\n",ans);
114 }
View Code

 

      

posted @ 2013-08-16 13:12  蛋丁  阅读(357)  评论(0编辑  收藏  举报