RoNgDaZhOnG

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

将田地上的食物取负,求图的最小费用流即为最大费用流的相反数。(ps第一次听说还可以这样用
思路:用spfa求最短路,沿着最短路增广。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<vector>
  6 #include<queue>
  7 #define maxn 0x3f3f3f3f
  8 using namespace std;
  9 struct edge{int to,cap,cost,rev;};
 10 vector <edge> E[5000];
 11 int ans,n,k,m,endd,start;
 12 int way_p[5000],way_n[5000];
 13 int num[100][100];
 14 
 15 void add_edge(int from,int to,int cap,int cost){
 16      E[from].push_back((edge){to,cap,cost,E[to].size()});
 17      E[to].push_back((edge){from,0,-cost,E[from].size()-1});
 18 }
 19 void build_E()
 20 {
 21      int sum=0,s=(2*m+n-1)*n/2;
 22      for(int i=0;i<n;i++){
 23              for(int j=0;j<i+m;j++){
 24                      sum++;
 25                      if(i==0){add_edge(0,sum,1,0);}
 26                      add_edge(sum,s+sum,1,-num[i][j]);
 27              }
 28      }
 29      endd=s+sum+1;
 30      sum=0;
 31      for(int i=0;i<n-1;i++){
 32              for(int j=0;j<i+m;j++){
 33                      sum++;
 34                      add_edge(sum+s,sum+i+m,1,0);
 35                      add_edge(sum+s,sum+i+m+1,1,0);
 36              }
 37      }
 38      for(int j=0;j<n+m-1;j++){
 39              sum++;
 40              add_edge(sum+s,endd,1,0);
 41      }
 42      start=endd+1;
 43      add_edge(start,0,k,0);
 44 }
 45 
 46 bool spfa()
 47 {
 48      bool used[5000]={0};
 49      int dist[5000];
 50      for(int i=0;i<=start;i++) dist[i]=maxn;
 51      queue <int> que;
 52      que.push(start);
 53      used[start]=true;
 54      dist[start]=0;
 55      while(!que.empty()){
 56                          int now=que.front();que.pop();
 57                          for(int i=0;i<E[now].size();i++){
 58                                  edge &e=E[now][i];
 59                                  if(e.cap>0 && dist[e.to]>e.cost+dist[now]){
 60                                             dist[e.to]=e.cost+dist[now];
 61                                             way_p[e.to]=now;
 62                                             way_n[e.to]=i;
 63                                             if(used[e.to]==false){
 64                                                                   que.push(e.to);
 65                                                                   used[e.to]=true;
 66                                             }
 67                                  }
 68                          }
 69                          used[now]=false;
 70      }
 71      if(dist[endd]>=maxn) return false;
 72      return true;
 73 }
 74 
 75 void work()
 76 {
 77       int now=endd,f=maxn;
 78       while(now!=start){
 79                         edge &e=E[way_p[now]][way_n[now]];
 80                         f=min(f,e.cap);
 81                         now=way_p[now];
 82       }
 83       now=endd;
 84       while(now!=start){
 85                         edge &e=E[way_p[now]][way_n[now]];
 86                         e.cap-=f;
 87                         E[e.to][e.rev].cap+=f;
 88                         ans+=(e.cost*f);
 89                         now=way_p[now];
 90       }
 91       return;
 92 }                    
 93      
 94      
 95              
 96      
 97 int main()
 98 {
 99     scanf("%d%d%d",&n,&m,&k);
100     for(int i=0;i<n;i++){
101             for(int j=0;j<i+m;j++){
102                     scanf("%d",&num[i][j]);
103             }
104     }
105     build_E();
106     while(spfa()){work();}
107     cout<<-ans<<endl;
108     
109     return 0;
110 }

 

posted on 2017-03-12 09:25  学无止境-1980  阅读(120)  评论(0编辑  收藏  举报