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

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

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

为了按照可行流的做法先减减去极大再加上极大,我又开了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.
View Code

 

posted on 2014-08-13 21:24  acphile  阅读(294)  评论(0编辑  收藏  举报