首页 > 代码库 > 【Codevs1227】方格取数2(费用流)
【Codevs1227】方格取数2(费用流)
题意:给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)
现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,
这样一共走K次,现在要求K次所达到的方格的数的和最大。
n<=50,k<=10
思路:费用流
将每个点裂成一个出点和一个入点(i,j,1..2),这个思路与最大流类似
(i,j,1)->(i,j,2) 连两条边:
容量为1,费用为a[i,j]
容量为K,费用为0
(i,j,2)->(i+1,j,1)连容量为K,费用为0的边 (i,j+1)类似
(n,n,2)->T 连流量为K,费用为0的边限制流量
跑最大费用最大流就行了,其实就是SPFA的三角不等式改个方向
1 var fan:array[1..200000]of longint; 2 q:array[0..20000]of longint; 3 head,vet,next,len1,len2:array[1..20000]of longint; 4 pre:array[1..20000,1..2]of longint; 5 inq:array[1..20000]of boolean; 6 dis:array[1..20000]of longint; 7 a:array[1..50,1..50]of longint; 8 num:array[1..50,1..50,1..2]of longint; 9 n,m,k1,i,j,k,tot,s,source,src:longint; 10 ans:int64; 11 12 function min(x,y:longint):longint; 13 begin 14 if x<y then exit(x); 15 exit(y); 16 end; 17 18 procedure add(a,b,c,d:longint); 19 begin 20 inc(tot); 21 next[tot]:=head[a]; 22 vet[tot]:=b; 23 len1[tot]:=c; 24 len2[tot]:=d; 25 head[a]:=tot; 26 27 inc(tot); 28 next[tot]:=head[b]; 29 vet[tot]:=a; 30 len1[tot]:=0; 31 len2[tot]:=-d; 32 head[b]:=tot; 33 end; 34 35 function spfa:boolean; 36 var u,t,w,i,e,v:longint; 37 begin 38 for i:=1 to s do 39 begin 40 dis[i]:=-maxlongint; 41 inq[i]:=false; 42 end; 43 t:=0; w:=1; q[1]:=source; inq[source]:=true; dis[source]:=0; 44 while t<w do 45 begin 46 inc(t); u:=q[t mod (s+5)]; 47 inq[u]:=false; 48 e:=head[u]; 49 while e<>0 do 50 begin 51 v:=vet[e]; 52 if (len1[e]>0)and(dis[u]+len2[e]>dis[v]) then 53 begin 54 pre[v,1]:=u; pre[v,2]:=e; 55 dis[v]:=dis[u]+len2[e]; 56 if not inq[v] then 57 begin 58 inc(w); q[w mod (s+5)]:=v; 59 inq[v]:=true; 60 end; 61 end; 62 e:=next[e]; 63 end; 64 end; 65 if dis[src]=-maxlongint then exit(false) 66 else exit(true); 67 end; 68 69 procedure mcf; 70 var k,e:longint; 71 t:int64; 72 begin 73 k:=src; t:=maxlongint; 74 while k<>source do 75 begin 76 e:=pre[k,2]; k:=pre[k,1]; 77 t:=min(t,len1[e]); 78 end; 79 k:=src; 80 while k<>source do 81 begin 82 e:=pre[k,2]; 83 len1[e]:=len1[e]-t; 84 len1[fan[e]]:=len1[fan[e]]+t; 85 ans:=ans+t*len2[e]; 86 k:=pre[k,1]; 87 end; 88 end; 89 90 begin 91 assign(input,‘codevs1227.in‘); reset(input); 92 assign(output,‘codevs1227.out‘); rewrite(output); 93 readln(n,k1); 94 for i:=1 to 200000 do 95 if i mod 2=1 then fan[i]:=i+1 96 else fan[i]:=i-1; 97 for i:=1 to n do 98 for j:=1 to n do read(a[i,j]); 99 for i:=1 to n do 100 for j:=1 to n do 101 for k:=1 to 2 do 102 begin 103 inc(s); num[i,j,k]:=s; 104 end; 105 for i:=1 to n do 106 for j:=1 to n do 107 begin 108 add(num[i,j,1],num[i,j,2],1,a[i,j]); 109 add(num[i,j,1],num[i,j,2],k1,0); 110 if j+1<=n then add(num[i,j,2],num[i,j+1,1],k1,0); 111 if i+1<=n then add(num[i,j,2],num[i+1,j,1],k1,0); 112 end; 113 source:=1; src:=s+1; inc(s); 114 add(num[n,n,2],src,k1,0); 115 while spfa do mcf; 116 writeln(ans); 117 close(input); 118 close(output); 119 end.
【Codevs1227】方格取数2(费用流)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。