zoukankan      html  css  js  c++  java
  • bzoj1497

    这道题让我涨姿势了

    对于这类问题,我们称作最大权闭合图问题

    就是每个点都有一个点权,要求选择一个点集,其中每个点的指向的点也在点集中,使这样一个点权和最大

    对于这种问题,我们添加源点s,汇点t

    对于点i,如果点权w是正的,我们连边s--->i,流量为w

    如果点权w是负的,我们连边i--->t,流量为-w

    然后我们我们原图中所有边流量设为inf即可

    最后的答案=正点权和-最小割(最大流)

    对于这道题,我们把用户和中转站看成点,

    对于每个用户,我们显然要由它指向对应的两个中转站,然后做最大权闭合图即可

    但是,这样做会tle,

    分析一下,为什么呢?因为有多达50000个用户

    再仔细观察题目,一共最多只有5000个中转站,

    我们知道,最大流的效率取决于找增广路的效率

    对于这幅图,我们不难发现,瓶颈边更容易出现在中转站一边

    于是我们可以反向建图,这不改变网络的最小割,并且能大大减少增广的次数

    反向建图是一个很重要的优化方法

      1 const inf=10000007;
      2 type node=record
      3        next,flow,point:longint;
      4      end;
      5 
      6 var edge:array[0..2000010] of node;
      7     p,h,numh,cur,pre:array[0..60010] of longint;
      8     n,m,i,j,t,x,y,z,len,s:longint;
      9 
     10 function min(a,b:longint):longint;
     11   begin
     12     if a>b then exit(b) else exit(a);
     13   end;
     14 
     15 procedure add(x,y,f:longint);
     16   begin
     17     inc(len);
     18     edge[len].point:=y;
     19     edge[len].flow:=f;
     20     edge[len].next:=p[x];
     21     p[x]:=len;
     22   end;
     23 
     24 function sap:longint;
     25   var u,i,j,q,neck,tmp,s:longint;
     26   begin
     27     u:=0;
     28     numh[0]:=t+1;
     29     sap:=0;
     30     while h[0]<t+1 do
     31     begin
     32       if u=t then
     33       begin
     34         neck:=inf;
     35         i:=0;
     36         while i<>t do
     37         begin
     38           j:=cur[i];
     39           if neck>edge[j].flow then
     40           begin
     41             neck:=edge[j].flow;
     42             s:=i;
     43           end;
     44           i:=edge[j].point;
     45         end;
     46         i:=0;
     47         while i<>t do
     48         begin
     49           j:=cur[i];
     50           dec(edge[j].flow,neck);
     51           inc(edge[j xor 1].flow,neck);
     52           i:=edge[j].point;
     53         end;
     54         sap:=sap+neck;
     55         u:=s;
     56       end;
     57       q:=-1;
     58       i:=p[u];
     59       while i<>-1 do
     60       begin
     61         j:=edge[i].point;
     62         if (edge[i].flow>0) and (h[u]=h[j]+1) then
     63         begin
     64           q:=i;
     65           break;
     66         end;
     67         i:=edge[i].next;
     68       end;
     69       if q<>-1 then
     70       begin
     71         cur[u]:=i;
     72         pre[j]:=u;
     73         u:=j;
     74       end
     75       else begin
     76         dec(numh[h[u]]);
     77         if numh[h[u]]=0 then exit;
     78         tmp:=t+1;
     79         i:=p[u];
     80         while i<>-1 do
     81         begin
     82           j:=edge[i].point;
     83           if edge[i].flow>0 then tmp:=min(tmp,h[j]);
     84           i:=edge[i].next;
     85         end;
     86         h[u]:=tmp+1;
     87         inc(numh[h[u]]);
     88         if u<>0 then u:=pre[u];
     89       end;
     90     end;
     91   end;
     92 
     93 begin
     94   readln(n,m);
     95   t:=n+m+1;
     96   len:=-1;
     97   fillchar(p,sizeof(p),255);
     98   for i:=1 to n do
     99   begin
    100     read(x);
    101     add(0,i,x);
    102     add(i,0,0);
    103   end;
    104   for i:=1 to m do
    105   begin
    106     readln(x,y,z);
    107     s:=s+z;
    108     add(n+i,t,z);
    109     add(t,n+i,0);
    110     add(x,n+i,inf);
    111     add(n+i,x,0);
    112     add(y,n+i,inf);
    113     add(n+i,y,0);
    114   end;
    115   writeln(s-sap);
    116 end.
    View Code
  • 相关阅读:
    ioctl函数用法小记
    scanf函数用法小记
    printf函数用法小记
    REDIS
    lspci 虚拟机网卡对应关系
    vmware安装ubuntu " Intel VT-x 处于禁用状态"
    win10远程桌面配置
    Win10如何彻底禁用小娜?彻底禁用小娜的方法
    为什么Windows7打开项目的方式是灰的不能修改
    以下suse11.3x64可以安装pycrypto-2.6.1
  • 原文地址:https://www.cnblogs.com/phile/p/4473232.html
Copyright © 2011-2022 走看看