zoukankan      html  css  js  c++  java
  • bzoj1927

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

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

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

    为了按照可行流的做法先减减去极大再加上极大,我又开了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
  • 相关阅读:
    bzoj 1217: [HNOI2003]消防局的设立
    [USACO09FEB]庙会班车Fair Shuttle
    bzoj 1052: [HAOI2007]覆盖问题
    bzoj 1974: [Sdoi2010]代码拍卖会
    bzoj 1835: [ZJOI2010]基站选址
    bzoj 1875: [SDOI2009]HH去散步
    bzoj 3295: [Cqoi2011]动态逆序对
    bzoj 2120: 数颜色
    P1032 字串变换
    简析拓扑排序
  • 原文地址:https://www.cnblogs.com/phile/p/4473171.html
Copyright © 2011-2022 走看看