zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    上海 政府性 常用网站
    linux 如何显示一个文件的某几行(中间几行)
    oracle 替换其中部分内容
    notepad++ 开始和结尾
    ll -d
    Mongodb总结3-稍微封装一下
    Mongodb总结3-稍微封装一下
    Mongodb总结2-Java版本的HelloWorld-CRUD例子
    Mongodb总结2-Java版本的HelloWorld-CRUD例子
    Mongodb总结1-启动和Shell脚本
  • 原文地址:https://www.cnblogs.com/0803yijia/p/2984391.html
Copyright © 2011-2022 走看看