Poj 3422 :Kaka's Matrix Travels (最大费用最大流)

题目连接: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 }

 

posted @ 2013-03-27 13:18  某某。  阅读(217)  评论(0编辑  收藏  举报