现在的位置: 首页 > 综合 > 正文

poj3422

2018年04月26日 ⁄ 综合 ⁄ 共 1887字 ⁄ 字号 评论关闭

【题意】

给定一个n*n的方格,每个方格里有一个数,从左上角出发,只能向下走或向右走,取过的数不计算权值,问走k次能得到的最大权值和

【输入】

第一行两个数字n、k

接下来一个n*n的矩阵描述棋盘

【输出】

一个数字表示最大的权值和

最大费用最大流,每个网格拆成两个点,之间连一条格子权值的流量为1的边和权值为0的流量为k-1的边,每个格子拆成的后一个点向能通往的格子的前一个点连一条权值为0流量为k的边,然后源点向(1,1)的前一个点连权值为0流量为k的边,(n,n)向汇点连权值为0流量为k的边,图就建好了,之后求费用流即可,虽然点最多有5002个,但是边十分稀疏,所以还是很轻松就能过的

program poj3422;
const
  s=0;
  e=5101;
var
  max,ans,p,n,k,i,j,tot:longint;
  dis,last,root:array [0..5101] of longint;
  dl,next,cost,point,flow:array [0..600001] of longint;

function hash (x,y,s:longint):longint;inline;
begin
  exit(x*n-n+y+s*n*n);
end;

function anti (now:longint):longint;inline;
begin
  if now and 1 = 1 then exit(now+1)
                   else exit(now-1);
end;

procedure connect (u,v,f,c:longint);inline;
begin
  inc(tot);
  point[tot]:=v;
  flow[tot]:=f;
  cost[tot]:=c;
  next[tot]:=root[u];
  root[u]:=tot;
end;

function mcmf:longint;
begin
  ans:=0;
  repeat
    fillchar(dis,sizeof(dis),0);
    dis[s]:=1;
    dl[0]:=s;
    tot:=0;
    i:=0;
    while i<=tot do
      begin
        k:=root[dl[i]];
        while k<>0 do
          begin
            if (flow[k]>0)and(dis[point[k]]<dis[dl[i]]+cost[k]) then
              begin
                dis[point[k]]:=dis[dl[i]]+cost[k];
                inc(tot);
                dl[tot]:=point[k];
                last[point[k]]:=k;
              end;
            k:=next[k];
          end;
        inc(i);
      end;
    if dis[e]<=1 then break;
    max:=maxlongint;;
    i:=e;
    while i<>s do
      begin
        if flow[last[i]]<max then max:=flow[last[i]];
        i:=point[anti(last[i])];
      end;
    ans:=ans+max*(dis[e]-1);
    i:=e;
    while i<>s do
      begin
        flow[last[i]]:=flow[last[i]]-max;
        flow[anti(last[i])]:=flow[anti(last[i])]+max;
        i:=point[anti(last[i])];
      end;
  until false;
  exit(ans);
end;


begin
  read(n,k);
  for i:=1 to n do
    for j:=1 to n do
      begin
        read(p);
        connect(hash(i,j,0),hash(i,j,1),1,p);
        connect(hash(i,j,1),hash(i,j,0),0,-p);
        connect(hash(i,j,0),hash(i,j,1),k-1,0);
        connect(hash(i,j,1),hash(i,j,0),0,0);
        if i+1<=n then
          begin
            connect(hash(i,j,1),hash(i+1,j,0),k,0);
            connect(hash(i+1,j,0),hash(i,j,1),0,0);
          end;
        if j+1<=n then
          begin
            connect(hash(i,j,1),hash(i,j+1,0),k,0);
            connect(hash(i,j+1,0),hash(i,j,1),0,0);
          end;
      end;
  connect(s,hash(1,1,0),k,0);
  connect(hash(1,1,0),s,0,0);
  connect(hash(n,n,1),e,k,0);
  connect(e,hash(n,n,1),0,0);
  writeln(mcmf);
end.
【上篇】
【下篇】

抱歉!评论已关闭.