以前写的1061但一直没懂,后来懂了但忘写解题报告了
做了1283顺便补一下吧
1061 我是orz https://www.byvoid.com/blog/noi-2008-employee/#more-916
这类类似线性规划的费用流构造,大概有这么几个步骤
首先找出不等式约束关系,然后添加辅助变量变成等式,并写出目标函数
然后通过做差构造,使每个变量都出现在两个等式中
每个等式整理成变量+常量=0 根据入流=出硫,我们把每个等式作为一个点
如果我们把等式左边系数为正作为入流,系数为负作为出流
则,对于每个变量,如果在等式j出现时系数为正,等式k系数为-,则k向j连边 流量为无穷,费用由目标函数决定
如果是常量,正则源点向这个等式连边,负则其向汇点连边,流量为常量的绝对值
然后我们就可以跑费用流了
1 const inf=2147483647; 2 3 type node=record 4 next,point,flow:longint; 5 cost:int64; 6 end; 7 8 var edge:array[0..1000010] of node; 9 c,p,cur,pre:array[0..1010] of longint; 10 d:array[0..1010] of int64; 11 v:array[0..1010] of boolean; 12 q:array[0..1000010] of longint; 13 b,e,w,i,j,n,m,len,t:longint; 14 ans:int64; 15 16 procedure add(x,y,f:longint;w:int64); 17 begin 18 inc(len); 19 edge[len].point:=y; 20 edge[len].flow:=f; 21 edge[len].cost:=w; 22 edge[len].next:=p[x]; 23 p[x]:=len; 24 end; 25 26 function spfa:boolean; 27 var f,r,x,y,i:longint; 28 begin 29 f:=1; 30 r:=1; 31 q[1]:=0; 32 for i:=1 to t do 33 d[i]:=inf; 34 fillchar(v,sizeof(v),false); 35 v[0]:=true; 36 while f<=r do 37 begin 38 x:=q[f]; 39 v[x]:=false; 40 i:=p[x]; 41 while i<>-1 do 42 begin 43 y:=edge[i].point; 44 if edge[i].flow>0 then 45 if d[y]>d[x]+edge[i].cost then 46 begin 47 d[y]:=d[x]+edge[i].cost; 48 pre[y]:=x; 49 cur[y]:=i; 50 if not v[y] then 51 begin 52 inc(r); 53 q[r]:=y; 54 v[y]:=true; 55 end; 56 end; 57 i:=edge[i].next; 58 end; 59 inc(f); 60 end; 61 if d[t]=inf then exit(false) else exit(true); 62 end; 63 64 procedure mincost; 65 var i,j:longint; 66 neck:int64; 67 begin 68 while spfa do 69 begin 70 neck:=inf; 71 i:=t; 72 while i<>0 do 73 begin 74 j:=cur[i]; 75 if edge[j].flow<neck then neck:=edge[j].flow; 76 i:=pre[i]; 77 end; 78 i:=t; 79 while i<>0 do 80 begin 81 j:=cur[i]; 82 dec(edge[j].flow,neck); 83 inc(edge[j xor 1].flow,neck); 84 i:=pre[i]; 85 end; 86 ans:=ans+d[t]*neck; 87 end; 88 end; 89 90 begin 91 readln(n,m); 92 len:=-1; 93 fillchar(p,sizeof(p),255); 94 t:=n+2; 95 for i:=1 to n do 96 read(c[i]); 97 for i:=1 to m do 98 begin 99 readln(b,e,w); 100 add(b,e+1,inf,w); 101 add(e+1,b,0,-w); 102 end; 103 for i:=1 to n+1 do 104 begin 105 w:=c[i]-c[i-1]; 106 if w>=0 then 107 begin 108 add(0,i,w,0); 109 add(i,0,-w,0); 110 end 111 else begin 112 add(i,t,-w,0); 113 add(t,i,0,0); 114 end; 115 if i>1 then 116 begin 117 add(i,i-1,inf,0); 118 add(i-1,i,0,0); 119 end; 120 end; 121 mincost; 122 writeln(ans); 123 end.
1 type node=record 2 po,next,flow,cost:longint; 3 end; 4 5 var e:array[0..800010] of node; 6 d,pre,cur,p:array[0..1010] of longint; 7 v:array[0..1010] of boolean; 8 q:array[0..1000010] of longint; 9 i,x,y,n,m,len,t,k:longint; 10 11 procedure add(x,y,f,c:longint); 12 begin 13 inc(len); 14 e[len].po:=y; 15 e[len].flow:=f; 16 e[len].cost:=c; 17 e[len].next:=p[x]; 18 p[x]:=len; 19 end; 20 21 procedure build(x,y,f,c:longint); 22 begin 23 add(x,y,f,c); 24 add(y,x,0,-c); 25 end; 26 27 function spfa:boolean; 28 var i,f,r,x,y:longint; 29 begin 30 fillchar(v,sizeof(v),false); 31 for i:=1 to t do 32 d[i]:=-1000000007; 33 d[0]:=0; 34 f:=1; 35 r:=1; 36 q[1]:=0; 37 while f<=r do 38 begin 39 x:=q[f]; 40 v[x]:=false; 41 i:=p[x]; 42 while i<>-1 do 43 begin 44 y:=e[i].po; 45 if e[i].flow>0 then 46 if d[y]<d[x]+e[i].cost then 47 begin 48 d[y]:=d[x]+e[i].cost; 49 pre[y]:=x; 50 cur[y]:=i; 51 if not v[y] then 52 begin 53 inc(r); 54 q[r]:=y; 55 v[y]:=true; 56 end; 57 end; 58 i:=e[i].next; 59 end; 60 inc(f); 61 end; 62 if d[t]<=0 then exit(false) else exit(true); 63 end; 64 65 function maxcost:longint; 66 var i,j:longint; 67 begin 68 maxcost:=0; 69 while spfa do 70 begin 71 i:=t; 72 while i<>0 do 73 begin 74 j:=cur[i]; 75 dec(e[j].flow); 76 inc(e[j xor 1].flow); 77 i:=pre[i]; 78 end; 79 maxcost:=maxcost+d[t]; 80 end; 81 end; 82 83 begin 84 readln(n,m,k); 85 len:=-1; 86 fillchar(p,sizeof(p),255); 87 t:=n+1; 88 for i:=1 to n do 89 begin 90 read(x); 91 y:=i+m; 92 if y>n then y:=t; 93 build(i,y,1,x); 94 build(i,i+1,k,0); 95 end; 96 build(0,1,k,0); 97 writeln(maxcost); 98 end.
UPD:这种题目可以直接跑单纯形
但是为什么单纯形能保证用最优解一定是整数呢,求神犇教导