标签:rom iostream 最大 log efi cap push work lib
将田地上的食物取负,求图的最小费用流即为最大费用流的相反数。(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 }
标签:rom iostream 最大 log efi cap push work lib
原文地址:http://www.cnblogs.com/rdzrdz-acm/p/6536988.html