[BZOJ2502]清理雪道解题报告|带下界的最小流

滑雪场坐落在FJ省西北部的若干座山上。

从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。

你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。

由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。

  题意就是给定一张DAG,求每条边起码经过一次求覆盖所有边的最小路径条数 如图

  这时的答案为4

  很容易看出,就是在每条边都经过一次的情况下求一次最小流

  即带有下界的最小流

  解决方法很简单:

  对于一条(x,y)

  从x到y连一条容量为1,费用为-INF的边,根据最小费用最大流的性质

  我们可以看出显然这条边是会流到的

  然后鉴于每条边经过的次数不止一次,所以从x到y再连一条容量为INF,费用为0的边

  源点向所有入度为0的点连边,所有出度为0的边向汇点连边

  但是显然求最大流是求不完的,什么时候停止呢?

  每次增广必定增广出的是费用最小的一条路径

  当图中还有边未经过的时候,增光出来的路径中毕竟有费用为-INF的边

  当图中所有的边都经过的时候,增广出的路径费用为0

  这个时候就可以停止了

  

  另外事后考虑了一个问题:

  这样做为什么能保证是最小流呢?

  每次增广然后标记感觉只是模拟

  但是会发现,每条未经过的边权值为-INF,和最小费用最大流结合

  保证每次选出的路径能尽量多填满一些边

  反向弧的存在又使结果的正确性有了更多重的保证

program xjt7;
const maxn = 110;maxm = 100010;INF = 10000000007;
var n,m,e,s,t,x,y:int64;
    i,j:longint;
    fa,next,link,w,cost,rec,son:array[-1..maxm]of int64;
    dis,opt,pos,pre,b,lea:array[-1..maxn]of int64;
    vis:array[-1..maxn]of boolean;

function min(a,b:int64):int64;
begin
    if a<b then exit(a) else exit(b);
end;

procedure add(x,y,z,cst:int64);
begin
    inc(e);fa[e]:=y;next[e]:=link[x];link[x]:=e;w[e]:=z;cost[e]:=cst;rec[e]:=e+1;son[e]:=x;
    inc(e);fa[e]:=x;next[e]:=link[y];link[y]:=e;w[e]:=0;cost[e]:=-cst;rec[e]:=e-1;son[e]:=y;
end;

function spfa:boolean;
var head,tail,x,j:int64;
begin
    fillchar(vis,sizeof(vis),true);
    fillchar(dis,sizeof(dis),63);
    head:=0;tail:=1;opt[1]:=s;dis[s]:=0;vis[s]:=false;
    while head<>tail do
    begin
        head:=(head+1) mod maxn;
        x:=opt[head];j:=link[x];
        while j<>0 do
        begin
            if (w[j]>0)and(dis[x]+cost[j]<dis[fa[j]]) then
            begin
                dis[fa[j]]:=dis[x]+cost[j];pre[fa[j]]:=j;
                if vis[fa[j]] then
                begin
                    vis[fa[j]]:=false;
                    tail:=(tail+1) mod maxn;
                    opt[tail]:=fa[j];
                end;
            end;
            j:=next[j];
        end;
        vis[x]:=true;
    end;
    if dis[t]<>dis[t+1] then exit(true);
    exit(false);
end;

procedure MCMF;
var sum,u,mn,ans:int64;
begin
    ans:=0;
    while spfa do
    begin
        sum:=0;
        u:=t;mn:=INF;
        while u<>s do
        begin
            mn:=min(mn,w[pre[u]]);
            u:=son[pre[u]];
        end;
        u:=t;
        while u<>s do
        begin
            inc(sum,mn*cost[pre[u]]);
            dec(w[pre[u]],mn);inc(w[rec[pre[u]]],mn);
            u:=son[pre[u]];
        end;
        if sum>0 then break;
        inc(ans,mn);
    end;
    writeln(ans);
end;

begin
    //assign(input,‘xjt7.in‘);reset(input);
    readln(n);
        fillchar(b,sizeof(b),0);
    for i:=1 to n do
    begin
        read(lea[i]);
        for j:=1 to lea[i] do
        begin
            read(y);add(i,y,1,-INF);add(i,y,INF,0);
            inc(b[y]);
        end;
        readln;
    end;
    s:=0;t:=n+1;
    for i:=1 to n do if b[i]=0 then add(s,i,INF,1);
    for i:=1 to n do if lea[i]=0 then add(i,t,INF,1);
    MCMF;
end.
时间: 2024-10-07 12:40:02

[BZOJ2502]清理雪道解题报告|带下界的最小流的相关文章

【BZOJ-2502】清理雪道 有上下界的网络流(有下界的最小流)

2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 594  Solved: 318[Submit][Status][Discuss] Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部.从降落的地点出

UVA1440 有下界的最小流

题意很简单: 给出一张有向图,每次你可以从图中的任意一点出发,经过若干条边后停止,然后问你最少走几次可以将图中的每条边都走过至少一次,并且要输出方案 这个转化为网络流的话,就相当于 求一个最小流,并且存在下界,即每条边至少走一次 这让我联想到很久之前的一道题,也是有向图,问走多少条路径可以将整个图中的每条边都走过,但是跟本题不同的是,那题是不允许重复走边的. 那道题目的解是这样的: 对于图中的每个点i,设D[i]为(i的入度-i的出度)的值,按照D[i]将图中的点分类:D[i]<0的称为"

[BZOJ2502]清理雪道 有上下界网络流(最小流)

2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MB Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部.从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道. 由于每次飞行的耗费是固定的,为了最小化耗费

bzoj2502 清理雪道

2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 307  Solved: 150 [Submit][Status][id=2502" style="color:blue; text-decoration:none">Discuss] Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中俯视,滑雪场能够看作一个有向无环图.每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你

bzoj-2502 清理雪道

题意: 给出一个n个点的拓扑图,每次从任意点出发到任意点结束,要求最终每条边都至少经过一次: 求最少要走多少次: n<=100: 题解: 最近在补一些网络流的姿势,于是就来刷刷上下界的网络流: 这道题网络流的模型比较特殊,对于每条边都有一个下界1,并且要求总流量最小: 所以这是个最小流,建图如下: 建立源S汇T: 每条原图的边(x,y)加入下界为1上界无穷的弧(x,y): 从S到每个点x连下界为0上界无穷的边(S,x): 从每个点x到T连下界为0上界无穷的边(x,T): 这个图中的S->T的最

ZOJ 3229 Shoot the Bullet 有源有汇带下界的最大流

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 Shoot the Bullet Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a u

POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是汇),求最小流 求法: 1.模仿可行流建图,但是不加t到s的INF边 2.跑最大流 3.加t到sINF边 4.跑最大流 5.如果两次答案相加不等于sum,无解; 6.如果有解,t到s的反边流量就是答案 #include<cstdio> #include<algorithm> #incl

[bzoj2502]清理雪道[上下界网络流]

bzoj状态里有两种,一种时间是个位数,一种是四位数,我就是四位数的那种,,,估计都是看了hzwer.. 1 #include <bits/stdc++.h> 2 3 #define INF 0x3f3f3f3f 4 5 using namespace std; 6 7 template<const int _n,const int _m> 8 struct Edge 9 { 10 struct Edge_base { int to,next,w; }e[_m]; int cnt,

[BZOJ3698]XWW的难题解题报告|上下界网络流|有源汇最大流

XWW是个影响力很大的人,他有很多的追随者.这些追随者都想要加入XWW教成为XWW的教徒.但是这并不容易,需要通过XWW的考核.XWW给你出了这么一个难题:XWW给你一个N*N的正实数矩阵A,满足XWW性.称一个N*N的矩阵满足XWW性当且仅当:(1)A[N][N]=0:(2)矩阵中每行的最后一个元素等于该行前N-1个数的和:(3)矩阵中每列的最后一个元素等于该列前N-1个数的和.现在你要给A中的数进行取整操作(可以是上取整或者下取整),使得最后的A矩阵仍然满足XWW性.同时XWW还要求A中的元