题目连接:http://poj.org/problem?id=3422
题目大意:n*N的格子,每个格子上都有数字,从左上角往右下角走,只能往右或者往下走,每走一个格子就加上格子上的分数,走过后格子上的分数为0,走K遍。问能够得到的最大的格子数是多少。
这题如果不是做费用流专题真心不会想不到费用最大流。
以为是K次,所以可以设容量为K。费用为当前格子的分数。然后因为每个点只记录一次分数,所以,用拆点来处理,用自己和自己连接一下,容量为1,费用为k然后再设一条边容量为K-1次,费用为0;然后就是设超级源点和汇点,容量为K费用为0;
我还有一个思路就是每条边的权值都为K,然后找到最大流的时候直接把COST清零。目前还没有实践。-------这是错误的。因为当执行完一次的时候cost+=a[t]*dis[t]的值是发生改变的,与真实值不同,但是注意即使改成+= a[t]同样不会正确,因为你改后,由于所有的残量都都为K这样找到一条增广路之后所有路都不能再重复走,所以是不对的。
View Code
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstdlib> 6 #include <queue> 7 #include <vector> 8 #define loop1(i,n) for(i = 1;i <= n;i++) 9 #define loop(i,n) for(i = 0;i <= n;i++) 10 const int inf = 1000000; 11 const int maxn = 50*50*3; 12 using namespace std; 13 struct node 14 { 15 int u,v,cap,flow,cost; 16 }; 17 vector<node> edge; 18 vector<int> g[maxn]; 19 void init(int n) 20 { 21 int i; 22 loop(i,n) 23 g[i].clear(); 24 25 edge.clear(); 26 } 27 void addedge(int u,int v,int cap,int flow,int cost) 28 { 29 edge.push_back((struct node){u,v,cap,flow,cost}); 30 edge.push_back((struct node){v,u,0,flow,-cost}); 31 int m; 32 m = edge.size(); 33 g[u].push_back(m-2); 34 g[v].push_back(m-1); 35 36 } 37 38 int vis[maxn]; 39 int pre[maxn]; 40 int dis[maxn]; 41 int a[maxn]; 42 int spfa(int s,int t,int n,int &flow,int &cost) 43 { 44 int i,u,v; 45 for(i = 0;i <= n;i++) 46 dis[i] = -1; 47 memset(vis,0,sizeof(vis)); 48 dis[s] = pre[s] = 0; 49 a[s] = inf; 50 queue<int>q; 51 q.push(s); 52 vis[s] = 1; 53 while(!q.empty()) 54 { 55 56 u = q.front(); 57 vis[u] = 0; 58 q.pop(); 59 60 for(i = 0;i < g[u].size();i++) 61 { 62 struct node & ei = edge[g[u][i]]; 63 v = ei.v; 64 if(ei.cap > ei.flow && dis[v] < dis[u]+ei.cost) 65 { 66 dis[v] = dis[u]+ei.cost; 67 pre[v] = g[u][i]; 68 a[v] = min(a[u],ei.cap-ei.flow); 69 if(!vis[v]) 70 q.push(v),vis[v] = 1; 71 } 72 } 73 } 74 if(dis[t] <= 0) 75 return 0; 76 77 flow += a[t]; 78 cost += a[t]*dis[t]; 79 80 u = t; 81 while(u != s) 82 { 83 edge[pre[u]].flow += a[t]; 84 edge[pre[u]^1].flow -= a[t]; 85 u = edge[pre[u]].u; 86 } 87 return 1; 88 } 89 90 int mcmf(int s,int t,int n) 91 { 92 int flow = 0; 93 int cost = 0; 94 while(spfa(s,t,n,flow,cost)); 95 96 return cost; 97 } 98 int main() 99 { 100 int n,k,i,j; 101 while(~scanf("%d %d",&n,&k)) 102 { 103 init(n*n*2+5); 104 loop1(i,n){ 105 loop1(j,n){ 106 int cost; 107 cin>>cost; 108 addedge((i-1)*n+j,(i-1)*n+j+n*n,1,0,cost); 109 addedge((i-1)*n+j,(i-1)*n+j+n*n,k,0,0); 110 if(i < n) 111 addedge((i-1)*n+j+n*n,i*n+j,k,0,0); 112 if(j < n) 113 addedge((i-1)*n+j+n*n,(i-1)*n+j+1,k,0,0); 114 } 115 } 116 117 addedge(0,1,k,0,0); 118 addedge(2*n*n,2*n*n+1,k,0,0); 119 int ans = 0; 120 ans = mcmf(0,n*n*2+1,n*n*2+2); 121 cout<<ans<<endl; 122 } 123 return 0; 124 }