出题人真 口袋迷

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

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

  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:注意这个程序虽然能过但有点问题,具体见后续

  1. const inf=;
  2.       bi=;
  3. type node=record
  4.        from,point,cost,flow,next:longint;
  5.      end;
  6.  
  7. var edge:array[..] of node;
  8.     q:array[..] of longint;
  9.     a:array[..,..] of longint;
  10.     p,pre,d:array[..] of longint;
  11.     v:array[..] of boolean;
  12.     len,x,y,z,ans,n,m,k,i,j,w,t:longint;
  13.  
  14. procedure add(x,y,f,w:longint);
  15.   begin
  16.     inc(len);
  17.     edge[len].from:=x;
  18.     edge[len].point:=y;
  19.     edge[len].flow:=f;
  20.     edge[len].cost:=w;
  21.     edge[len].next:=p[x];
  22.     p[x]:=len;
  23.   end;
  24.  
  25. function spfa:boolean;              //网络流基本模板
  26.   var i,f,r,x,y:longint;
  27.   begin
  28.     fillchar(v,sizeof(v),false);
  29.     for i:= to t do
  30.       d[i]:=inf;
  31.     d[]:=;
  32.     f:=;
  33.     r:=;
  34.     q[]:=;
  35.     v[]:=true;
  36.     while f<=r do
  37.     begin
  38.       x:=q[f];
  39.       v[x]:=false;
  40.       i:=p[x];
  41.       while i<>- do
  42.       begin
  43.         y:=edge[i].point;
  44.         if edge[i].flow> then
  45.         begin
  46.           if d[y]>d[x]+edge[i].cost then
  47.           begin
  48.             d[y]:=d[x]+edge[i].cost;
  49.             pre[y]:=i;
  50.             if not v[y] then
  51.             begin
  52.               v[y]:=true;
  53.               inc(r);
  54.               q[r]:=y;
  55.             end;
  56.           end;
  57.         end;
  58.         i:=edge[i].next;
  59.       end;
  60.       inc(f);
  61.     end;
  62.     if d[t]=inf then exit(false) else exit(true);
  63.   end;
  64.  
  65. procedure mincost;                  //费用流
  66.   var i,j:longint;
  67.   begin
  68.     while spfa do
  69.     begin
  70.       i:=t;
  71.       while i<> do
  72.       begin
  73.         j:=pre[i];
  74.         dec(edge[j].flow);           //每次只会流一个人
  75.         inc(edge[j xor ].flow);
  76.         i:=edge[j].from;
  77.       end;
  78.       ans:=ans+d[t];
  79.     end;
  80.   end;
  81.  
  82. begin
  83.   readln(n,m,w);
  84.   inc(n);
  85.   len:=-;
  86.   fillchar(p,sizeof(p),);
  87.   for i:= to n do
  88.   begin
  89.     for j:= to n do
  90.       a[i,j]:=inf;
  91.     a[i,i]:=;
  92.   end;
  93.   t:=*n+;
  94.   for i:= to m do
  95.   begin
  96.     readln(x,y,z);
  97.     inc(x);                //仅仅是为了方便
  98.     inc(y);
  99.     if a[x,y]>z then
  100.     begin
  101.       a[x,y]:=z;
  102.       a[y,x]:=z;
  103.     end;
  104.   end;
  105.   add(,,w,);            //一共有w个人,自然流量为w
  106.   add(,,,);
  107.   for i:= to n do
  108.   begin
  109.     add(i,i+n,,-bi);     //处理下界网络流简单快捷的方法
  110.     add(i+n,i,,bi);
  111.     add(i+n,t,,);       //每个人都可以停在当前点不走,流直接流出
  112.     add(t,n+i,,);
  113.   end;
  114.   for k:= to n do
  115.   begin
  116.     for i:= to n do
  117.       if i<>k then
  118.         for j:= to n do
  119.           if (i<>j) and (j<>k) then
  120.             a[i,j]:=min(a[i,j],a[i,k]+a[k,j]);
  121.     if k<> then
  122.     begin
  123.       add(,k,,a[,k]);         
  124.       add(k,,,-a[,k]);
  125.     end;
  126.     for i:= to k- do         // 边做边建图,显然这时候,i到k的最短路径一定是由编号小于k的点更新来的   
  127.     begin
  128.       add(i+n,k,,a[i,k]);     //这个地方和上面流量为什么是1呢?点i到下一个点j可行最小路径只要走一次,
  129.                             如果这条路径实际需要走多次的话,那必然有点i到点k的可行最短路径由ij可行最短路更新的来
  130.                             于是下一次找增广路的时候,我们直接走ik之间最短路即可
  131.                             所以这里我们把每条路径流量限制为1,这样寻找增广路的速度会更快
  132.                             (当然像考试时拿不准还是写成inf 
  133.       add(k,i+n,,-a[i,k]);
  134.     end;
  135.   end;
  136.   mincost;
  137.   writeln(ans+(n-)*bi);    //修正ans
  138. 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. [译]Java Thread wait, notify和notifyAll示例

    Java Thread wait, notify和notifyAll示例 Java上的Object类定义了三个final方法用于不同线程间关于某资源上的锁状态交互,这三个方法是:wait(), not ...

  2. shell脚本编程之for语句、if语句使用介绍

    介绍了shell脚本编程之for语句.if语句的使用方法. 上部: 面向过程: 顺序执行 选择执行: if, case 循环执行: for, while, until 一.for语句 格式:      ...

  3. 2015年1月最新中国行政区划县及以上代码mysql数据库

    中华人民共和国国家统计局>> 行政区划代码>>mysql数据格式 截图如下 行政区划mysql数据库文件下载:nation.zip 转载:http://www.sdhack.c ...

  4. 《WPF程序设计指南》读书笔记——第1章 应用程序与窗口

    1.空白WPF项目的创建: 1)新建项目:在VS2010中,文件-新建-项目-visual c#-windows-空项目: 2)添加引用:PresentationFramework,Presentat ...

  5. OOP三类继承的区别

    OOP继承的区别提纲: 1. 普通类继承,并非一定要重写父类方法.2. 抽象类继承,如果子类也是一个抽象类,并不要求一定重写父类方法.如果子类不是抽象类,则要求子类一定要实现父类中的抽象方法.3. 接 ...

  6. 收录一个简单的css类库

    /* CSS liberary */.yahei {    font-family: "Microsoft Yahei", "Tahoma", "Si ...

  7. Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解

    在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...

  8. 让<未将对象引用到实例>见鬼去吧!

    未将对象引用到实例,即NullReferenceException异常,我相信这是c#编程中最常见的错误之一,至少我在做项目的过程中,有很多时候都会抛出这个异常.每当这个异常出现的时候,我都会头皮一紧 ...

  9. poj 2060 Taxi Cab Scheme (最小路径覆盖)

    http://poj.org/problem?id=2060 Taxi Cab Scheme Time Limit: 1000MS   Memory Limit: 30000K Total Submi ...

  10. GitHub 有哪些优秀的项目

    GitHub 有哪些优秀的项目 http://www.zhihu.com/question/20584141