看到这道题不难想到费用流吧,但是怎么做呢?
一开始看到“每个点都恰好走一次”,我首先想到的有下界最小费用流,
然后发现这没有满足最大流的条件,然后又连边松弛掉多余的流
为了按照可行流的做法先减减去极大再加上极大,我又开了int64
最后弄啊弄,AC了倒是,但是跑出了一个很恶心的14s+,
感觉不是这样做,仔细想想,每个点都恰好走一次,并且这是一个DAG图----->最小路径覆盖!
这才正解,只不过这里是带费用的,其实也没什么
首先我们先不管瞬移模式,先按拆点
对于图上的边(i,j),连边i--->j' 流量为1,费用为边长
然后添加超级源汇,源汇和两部分点连边
下面考虑瞬移,连边s---->i' 流量为1,费用为瞬移时间
这样就搞定了
1 const inf=100000007; 2 3 type node=record 4 flow,point,next,cost:longint; 5 end; 6 7 var edge:array[0..1001000] of node; 8 d,a:array[0..2000] of longint; 9 p,pre,cur:array[0..2000] of longint; 10 q:array[0..2001000] of longint; 11 v:array[0..2000] of boolean; 12 z,ans,m,x,y,i,j,n,s,t,len:longint; 13 14 procedure add(x,y,f,w:longint); 15 begin 16 inc(len); 17 edge[len].point:=y; 18 edge[len].flow:=f; 19 edge[len].cost:=w; 20 edge[len].next:=p[x]; 21 p[x]:=len; 22 end; 23 24 procedure swap(var a,b:longint); 25 var c:longint; 26 begin 27 c:=a; 28 a:=b; 29 b:=c; 30 end; 31 32 function spfa:boolean; 33 var i,f,r,x,y:longint; 34 begin 35 for i:=1 to t do 36 d[i]:=inf; 37 d[0]:=0; 38 fillchar(v,sizeof(v),false); 39 v[0]:=true; 40 f:=1; 41 r:=1; 42 q[1]:=0; 43 while f<=r do 44 begin 45 x:=q[f]; 46 v[x]:=false; 47 i:=p[x]; 48 while i<>-1 do 49 begin 50 y:=edge[i].point; 51 if edge[i].flow>0 then 52 if d[y]>d[x]+edge[i].cost then 53 begin 54 d[y]:=d[x]+edge[i].cost; 55 pre[y]:=x; 56 cur[y]:=i; 57 if not v[y] then 58 begin 59 inc(r); 60 q[r]:=y; 61 v[y]:=true; 62 end; 63 end; 64 i:=edge[i].next; 65 end; 66 inc(f); 67 end; 68 if d[t]=inf then exit(false) else exit(true); 69 end; 70 71 procedure mincost; 72 var i,j:longint; 73 begin 74 while spfa do 75 begin 76 i:=t; 77 while i<>0 do 78 begin 79 j:=cur[i]; 80 dec(edge[j].flow); 81 inc(edge[j xor 1].flow); 82 i:=pre[i]; 83 end; 84 ans:=ans+d[t]; 85 end; 86 end; 87 88 begin 89 len:=-1; 90 fillchar(p,sizeof(p),255); 91 readln(n,m); 92 for i:=1 to n do 93 read(a[i]); 94 for i:=1 to m do 95 begin 96 readln(x,y,z); 97 if x>y then swap(x,y); 98 add(x,y+n,1,z); 99 add(y+n,x,0,-z); 100 end; 101 t:=2*n+1; 102 for i:=1 to n do 103 begin 104 add(0,i+n,1,a[i]); 105 add(i+n,0,0,-a[i]); 106 add(0,i,1,0); 107 add(i,0,0,0); 108 add(i+n,t,1,0); 109 add(t,i+n,0,0); 110 end; 111 mincost; 112 writeln(ans); 113 end.