看到这道题不难想到费用流吧,但是怎么做呢?

一开始看到“每个点都恰好走一次”,我首先想到的有下界最小费用流,

然后发现这没有满足最大流的条件,然后又连边松弛掉多余的流

为了按照可行流的做法先减减去极大再加上极大,我又开了int64

最后弄啊弄,AC了倒是,但是跑出了一个很恶心的14s+,

感觉不是这样做,仔细想想,每个点都恰好走一次,并且这是一个DAG图----->最小路径覆盖!

这才正解,只不过这里是带费用的,其实也没什么

首先我们先不管瞬移模式,先按拆点

对于图上的边(i,j),连边i--->j' 流量为1,费用为边长

然后添加超级源汇,源汇和两部分点连边

下面考虑瞬移,连边s---->i' 流量为1,费用为瞬移时间

这样就搞定了

 const inf=;

 type node=record
       flow,point,next,cost:longint;
     end; var edge:array[..] of node;
    d,a:array[..] of longint;
    p,pre,cur:array[..] of longint;
    q:array[..] of longint;
    v:array[..] of boolean;
    z,ans,m,x,y,i,j,n,s,t,len:longint; procedure add(x,y,f,w:longint);
  begin
    inc(len);
    edge[len].point:=y;
    edge[len].flow:=f;
    edge[len].cost:=w;
    edge[len].next:=p[x];
    p[x]:=len;
  end; procedure swap(var a,b:longint);
  var c:longint;
  begin
    c:=a;
    a:=b;
    b:=c;
  end; function spfa:boolean;
  var i,f,r,x,y:longint;
  begin
    for i:= to t do
      d[i]:=inf;
    d[]:=;
    fillchar(v,sizeof(v),false);
    v[]:=true;
    f:=;
    r:=;
    q[]:=;
    while f<=r do
    begin
      x:=q[f];
      v[x]:=false;
      i:=p[x];
      while i<>- do
      begin
        y:=edge[i].point;
        if edge[i].flow> then
          if d[y]>d[x]+edge[i].cost then
          begin
            d[y]:=d[x]+edge[i].cost;
            pre[y]:=x;
            cur[y]:=i;
            if not v[y] then
            begin
              inc(r);
              q[r]:=y;
              v[y]:=true;
            end;
          end;
        i:=edge[i].next;
      end;
      inc(f);
    end;
    if d[t]=inf then exit(false) else exit(true);
  end; procedure mincost;
  var i,j:longint;
  begin
    while spfa do
    begin
      i:=t;
      while i<> do
      begin
        j:=cur[i];
        dec(edge[j].flow);
        inc(edge[j xor ].flow);
        i:=pre[i];
      end;
      ans:=ans+d[t];
    end;
  end; begin
  len:=-;
  fillchar(p,sizeof(p),);
  readln(n,m);
  for i:= to n do
    read(a[i]);
  for i:= to m do
  begin
    readln(x,y,z);
    if x>y then swap(x,y);
    add(x,y+n,,z);
    add(y+n,x,,-z);
  end;
  t:=*n+;
  for i:= to n do
  begin
    add(,i+n,,a[i]);
    add(i+n,,,-a[i]);
    add(,i,,);
    add(i,,,);
    add(i+n,t,,);
    add(t,i+n,,);
  end;
  mincost;
  writeln(ans);
end.
04-25 23:02