出题人真 口袋迷

很容易发现这是一道费用流的题目

很显然这个问题有两个难点:

  1. 保证走到某个点时之前序号的点都被走过

  2. 保证每个点都走

对于1,我们换个说法,一个人走到该点时经过的点的序号都小于该点----->3

只要满足了2和3,就一定满足1

现在来看3,也就是说两个点之间的最短路i,j,必须由k(k<j) 来更新

很像是floyd,事实上我们只要改一改floyd就能满足3

下面的问题就是,怎么满足2,也就是称之为有下界的网络流

这里学习了一个非常厉害的方法解决此类问题:

加无穷小边连接汇点

对于这道题,我们把除了0号点的以外点拆成两个点,之间连两条边

一条流量为1,费用为负无穷;一条流量为无穷,费用为0

什么意思呢?第二条边好理解,表示每个点都可以被经过无数次

第一条边什么意思呢?保证每个点都被走过;

因为这条边的费用为极小边,根据费用流的算法,这条边一定会被走过,等价于这个点一定会被走过;

最后计算总费用的时候我们再把负费用弄掉即可

后记:

话说,我在省选的前几天做了这道题目,说了都是泪啊;

考试的时候D2 T1同样也是有下界的网络流,比这题还简单,

这不过是边的容量下界是1,(一样的道理,在每条边的基础上加一条流为1,费用为这条边的费用-极小量即可)

我也很好的写出了处理有下界的网络流的方法;

可我偏偏脑抽的用到了邻接矩阵,这样就毫无意外的被重边卡死了T T

自作孽,不可活…………

UPD:注意这个程序虽然能过但有点问题,具体见后续

 const inf=;
      bi=;
type node=record
       from,point,cost,flow,next:longint;
     end; var edge:array[..] of node;
    q:array[..] of longint;
    a:array[..,..] of longint;
    p,pre,d:array[..] of longint;
    v:array[..] of boolean;
    len,x,y,z,ans,n,m,k,i,j,w,t:longint; procedure add(x,y,f,w:longint);
  begin
    inc(len);
    edge[len].from:=x;
    edge[len].point:=y;
    edge[len].flow:=f;
    edge[len].cost:=w;
    edge[len].next:=p[x];
    p[x]:=len;
  end; function spfa:boolean;              //网络流基本模板
  var i,f,r,x,y:longint;
  begin
    fillchar(v,sizeof(v),false);
    for i:= to t do
      d[i]:=inf;
    d[]:=;
    f:=;
    r:=;
    q[]:=;
    v[]:=true;
    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
        begin
          if d[y]>d[x]+edge[i].cost then
          begin
            d[y]:=d[x]+edge[i].cost;
            pre[y]:=i;
            if not v[y] then
            begin
              v[y]:=true;
              inc(r);
              q[r]:=y;
            end;
          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:=pre[i];
        dec(edge[j].flow);           //每次只会流一个人
        inc(edge[j xor ].flow);
        i:=edge[j].from;
      end;
      ans:=ans+d[t];
    end;
  end; begin
  readln(n,m,w);
  inc(n);
  len:=-;
  fillchar(p,sizeof(p),);
  for i:= to n do
  begin
    for j:= to n do
      a[i,j]:=inf;
    a[i,i]:=;
  end;
  t:=*n+;
  for i:= to m do
  begin
    readln(x,y,z);
    inc(x);                //仅仅是为了方便
    inc(y);
    if a[x,y]>z then
    begin
      a[x,y]:=z;
      a[y,x]:=z;
    end;
  end;
  add(,,w,);            //一共有w个人,自然流量为w
  add(,,,);
  for i:= to n do
  begin
    add(i,i+n,,-bi);     //处理下界网络流简单快捷的方法
    add(i+n,i,,bi);
    add(i+n,t,,);       //每个人都可以停在当前点不走,流直接流出
    add(t,n+i,,);
  end;
  for k:= to n do
  begin
    for i:= to n do
      if i<>k then
        for j:= to n do
          if (i<>j) and (j<>k) then
            a[i,j]:=min(a[i,j],a[i,k]+a[k,j]);
    if k<> then
    begin
      add(,k,,a[,k]);         
      add(k,,,-a[,k]);
    end;
    for i:= to k- do         // 边做边建图,显然这时候,i到k的最短路径一定是由编号小于k的点更新来的   
    begin
      add(i+n,k,,a[i,k]);     //这个地方和上面流量为什么是1呢?点i到下一个点j可行最小路径只要走一次,
                            如果这条路径实际需要走多次的话,那必然有点i到点k的可行最短路径由ij可行最短路更新的来
                            于是下一次找增广路的时候,我们直接走ik之间最短路即可
                            所以这里我们把每条路径流量限制为1,这样寻找增广路的速度会更快
                            (当然像考试时拿不准还是写成inf吧 
      add(k,i+n,,-a[i,k]);
    end;
  end;
  mincost;
  writeln(ans+(n-)*bi);    //修正ans
end.

bzoj2324的更多相关文章

  1. bzoj2324后续思考

    昨天写bzoj2324的解题报告的时候突然隐隐约约发现了我程序的一点问题 睡了一觉之后找到了反例 如下: 4 4 2 0 1 2 1 2 1 2 3 2 2 4 2 对于这个测试数据,显然最短路径和为 ...

  2. 【BZOJ2324】[ZJOI2011]营救皮卡丘(网络流,费用流)

    [BZOJ2324][ZJOI2011]营救皮卡丘(网络流,费用流) 题面 BZOJ 洛谷 题解 如果考虑每个人走的路径,就会很麻烦. 转过来考虑每个人破坏的点集,这样子每个人可以得到一个上升的序列. ...

  3. BZOJ2324 ZJOI2011营救皮卡丘(floyd+上下界费用流)

    虽然不一定每次都是由编号小的点向编号大的走,但一个人摧毁的顺序一定是从编号小的到编号大的.那么在摧毁据点x的过程中,其只能经过编号小于x的点.并且这样一定合法,因为可以控制其他人先去摧毁所经过的点.那 ...

  4. 【BZOJ2324】[ZJOI2011]营救皮卡丘 有上下界费用流

    [BZOJ2324][ZJOI2011]营救皮卡丘 Description 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的 ...

  5. BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理

    准备一周多的期末,各种爆炸,回来后状态下滑巨快...调了一晚上+80%下午 2324: [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec Memory Limit: 256 MB ...

  6. bzoj2324营救皮卡丘

    费用流. 建图比较重要. 1.S->id[0][0] flow=k. 表示k条路径. 2.S->id[i][0] flow=1, 每次消耗1流量就补充1流量. 3.id[i][1]-> ...

  7. BZOJ2324: [ZJOI2011]营救皮卡丘

    2324: [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1359  Solved: 522[Submit][Stat ...

  8. [BZOJ2324][ZJOI2011][最小费用最大流]营救皮卡丘

    [Problem Description] 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队 ...

  9. 【bzoj2324】[ZJOI2011]营救皮卡丘 最短路-Floyd+有上下界费用流

    原文地址:http://www.cnblogs.com/GXZlegend/p/6832504.html 题目描述 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘 ...

随机推荐

  1. 《C和指针》 读书笔记 -- 第8章 数组

    1.在C中,数组名的值是一个指针常量而不是指针变量,也就是数组第一个元素的地址. 2.数组和指针的区别: 声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值是 ...

  2. 怎样下载安装Firebug和使用Firebug

    Firebug是基于火狐(FireFox)浏览器的一个插件,它的作用是给Web页面开发者一个很好的测试前端页面代码的工具.所以深受网页开发者或网页布局爱好者的喜爱.像我们用DIV+CSS和html所写 ...

  3. 关于帝国cms 列表页SEO优化的问题

    一般列表页面中,我们都需要带分页信息区分当前页号,为区分第一页,和第一页后的其他所有分页页面.我们推荐的做法为:第一页显示正常的标题,从第二页开始便显示xxxxx-第2页-xxxx网.做法是.修改帝国 ...

  4. poj 2774 Long Long Message 后缀数组LCP理解

    题目链接 题意:给两个长度不超过1e5的字符串,问两个字符串的连续公共子串最大长度为多少? 思路:两个字符串连接之后直接后缀数组+LCP,在height中找出max同时满足一左一右即可: #inclu ...

  5. C语言-人狼羊菜问题-最容易看懂的解决方法及代码

    题目描述:农夫需要把狼.羊.菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷吃菜,狼会吃羊.请考虑一种方法,让农夫能够 ...

  6. dom树的介绍,及原理分析

    三.解析和DOM树的构建 1.解析: 由于解析渲染引擎是一个非常重要的过程,我们将会一步步的深入,现在让我们来介绍解析. 解析一个文档,意味着把它转换为一个有意义的结构——代码可以了解和使用的东西,解 ...

  7. oracle中的隐式提交(auto commit)

    通常我们执行sql或pl/sql时,需要我们手工提交.这样才能使所做的更改永久保存到数据库. 但有时即使我们没有在sql或pl/sql中发出commit命令,所做的更改也会被提交.这种提交是在某些特定 ...

  8. 然爸读书笔记(2014-10)----Bootsrap用户手册

    本来其实这方面的知识,可以直接在网站上看,但是自己是web前端的小白.基本不懂.所以,还是买一本书来看,更好些.体现出我对前端的重视. Bootstrap是快速开发Web应用程序的前端工具包.它是一个 ...

  9. 使用Yeoman搭建 AngularJS 应用 (7) —— 让我们搭建一个网页应用

    原文地址:http://yeoman.io/codelab/preview-inbrowser.html 开启你的服务 运行Grunt任务,通过输入下面的命令来创建一个本地Node的http服务,地址 ...

  10. PD code与name联动(取消)设置

    在powerdesign中,code与name老是联动,修改了name中的数据,code随之修改,影响效率,设置Tools-General Options-Dialog  中的Name to Code ...