POJ 2135 Farm Tour(最小费用最大流,变形)

 

 

题意:给一个无向图,FJ要从1号点出发到达n号点,再返回到1号点,但是路一旦走过了就会销毁(即回去不能经过),每条路长度不同,那么完成这趟旅行要走多长的路?(注:会有重边,点号无序,无向图!)

 

思路:

  有重边,要用邻接表。所给的每条边都要变成4条有向边!否则可能一开始就到达不了终点了。最后要再加上一个源点和汇点,容量cap(源点,1)=2,指定只能走两次,再规定其他所给的边的容量是1就行了,当边被走过了,就自动增加了流,也就走不了了。

  解释看代码更清晰。

 

  1 //#pragma comment(linker,"/STACK:102400000,102400000")

  2 #include <iostream>

  3 #include <stdio.h>

  4 #include <string.h>

  5 #include <vector>

  6 #include <stack>

  7 #include <algorithm>

  8 #include <map>

  9 //#include <bits/stdc++.h>

 10 #define LL long long

 11 #define pii pair<int,int>

 12 #define INF 0x7f7f7f7f

 13 using namespace std;

 14 const int N=10000+5;

 15 vector<int> vect[N];

 16 struct node

 17 {

 18     int from;

 19     int to;

 20     int cost;

 21     int cap;

 22     int flow;

 23 }edge[N*4];     //边数是4*M的大小

 24 

 25 int edge_num;   //边的上限

 26 int f[N];       //

 27 int path[N];    //记录路径

 28 int c[N];       //记录费用

 29 bool in[N];     //是否在queue中

 30 

 31 void add_node(int a, int b, int c, int ca, int fl)

 32 {

 33     edge[edge_num].from=a;

 34     edge[edge_num].to=b;

 35     edge[edge_num].cost=c;

 36     edge[edge_num].cap=ca;

 37     edge[edge_num].flow=fl;

 38     vect[a].push_back(edge_num++);

 39 }

 40 

 41 

 42 LL spfa(int s,int e)

 43 {

 44     deque<int> que;

 45     que.push_back(s);

 46     c[s]=0;

 47     f[s]=INF;

 48     in[s]=1;

 49     while(!que.empty())

 50     {

 51         int x=que.front();

 52         que.pop_front();

 53         in[x]=0;

 54         for(int i=0; i<vect[x].size(); i++)

 55         {

 56             node t=edge[vect[x][i]];

 57             if(t.cap>t.flow && c[t.to]>c[t.from]+t.cost)  //能流过,且费用更小即可更新。

 58             {

 59                 path[t.to]=vect[x][i];          //记边号,方便更新flow

 60                 c[t.to]=c[t.from]+t.cost;       //更新cost,相当于距离

 61                 f[t.to]=min(f[t.from], t.cap-t.flow);

 62                 if(!in[t.to])

 63                 {

 64                     que.push_back(t.to);

 65                     in[t.to]=1;

 66                 }

 67             }

 68         }

 69     }

 70     return c[e];

 71 }

 72 

 73 int m;

 74 

 75 int mcmf(int s, int e)

 76 {

 77     LL ans=0;

 78     while(1)

 79     {

 80         memset(f, 0, sizeof(f));

 81         memset(c, 0x7f, sizeof(c));

 82         memset(in, 0, sizeof(in));

 83         memset(path, 0, sizeof(path));

 84 

 85         int tmp=spfa(s, e);

 86         if(tmp==INF)    return ans;

 87         ans+=tmp*f[e];   //这是最小费用。注:每次的流可能不是1。

 88 

 89         int ed=e;

 90         while(ed!=s)

 91         {

 92             int en=path[ed];

 93             edge[en].flow+=f[e];

 94             edge[en^1].flow-=f[e];

 95             ed=edge[en].from;

 96             //cout<<edge[en].from<<"-"<<edge[en].to<<endl;

 97         }

 98     }

 99 }

100 

101 

102 

103 

104 

105 int main()

106 {

107     freopen("input.txt", "r", stdin);

108     int  n, a, b, c;

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

110     {

111         for(int i=n*2; i>=0; i--)   vect[i].clear();

112         edge_num=0;

113         for(int i=0; i<m; i++)

114         {

115             scanf("%d%d%d",&a,&b,&c);

116             add_node(a,b,c,1,0);    //4条有向边。

117             add_node(b,a,-c,0,0);

118 

119             add_node(b,a,c,1,0);

120             add_node(a,b,-c,0,0);

121         }

122         add_node(0,1,0,2,0);        //加多2条边

123         add_node(1,0,0,0,0);        //加这条无意义,但是更新flow时更方便

124         add_node(n,n+1,0,2,0);

125         add_node(n+1,n,0,0,0);

126 

127         printf("%lld\n",mcmf(0, n+1));

128     }

129 

130 

131     return 0;

132 }
AC代码

 

你可能感兴趣的:(poj)