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

2502: 清理雪道

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

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

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

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

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

Input

输入文件的第一行包含一个整数n (2 <= n <= 100) – 代表滑雪场的地点的数量。接下来的n行,描述1~n号地点出发的斜坡,第i行的第一个数为mi (0 <= mi < n) ,后面共有mi个整数,由空格隔开,每个整数aij互不相同,代表从地点i下降到地点aij的斜坡。每个地点至少有一个斜坡与之相连。

Output

输出文件的第一行是一个整数k – 直升飞机的最少飞行次数。

Sample Input

8
1 3
1 7
2 4 5
1 8
1 8
0
2 6 5
0

Sample Output

4

题解:

接触到的第一道上下界网络流题目……我怎么什么题都不会啊.jpg

如果你对上下界网络流没有接触的话,首先安利一波liu_runda学长的学习笔记,

讲的十分详细:http://www.cnblogs.com/liu-runda/p/6262832.html

在你已经会来上下界网络流之后……

大概这是一道水题吧233

先计算出附加流,然后从附加源ss跑到附加汇tt的最大流,

这样我们就得到了一个可行流,在t->s的弧上面把可行流的流量ans1提取出来。

然后我们去掉t->s的弧以及ss,tt两个附加点,再跑一边t->s最大流

由于反向边的流量增加意味着正向边的流量减少,所以设这样跑出来的最大流是ans2,答案就是ans1-ans2。

这样我们就解决了本题。代码实现:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=210,inf=0x7fffffff;
 6 struct edge{int zhong,next,flow;};
 7 struct NetWork
 8 {
 9     int n,S,T,e,adj[N],cur[N];
10     int hd,tl,que[N],dist[N],gap[N];
11     edge s[N<<6];
12     inline void intn(int sz)
13     {
14         n=sz,e=1,memset(adj,0,sizeof(adj));
15         memset(dist,0,sizeof(dist));
16         memset(gap,0,sizeof(gap));
17     }
18     inline void add(int qi,int zhong,int flow)
19         {s[++e].zhong=zhong;s[e].next=adj[qi];adj[qi]=e;s[e].flow=flow;}
20     inline void bfs()
21     {
22         hd=1,tl=0,dist[T]=1,que[++tl]=T;
23         register int i,x,u;
24         while(hd<=tl)
25             for(x=que[hd++],++gap[dist[x]],i=adj[x];i;i=s[i].next)
26                 if(!dist[s[i].zhong])
27                     dist[s[i].zhong]=dist[x]+1,que[++tl]=s[i].zhong;
28     }
29     int Shoot(int rt,int maxf)
30     {
31         if(rt==T||!maxf)return maxf;
32         register int i,f,ret=0;
33         for(i=cur[rt];i;i=s[i].next)
34             if(s[i].flow&&dist[rt]==dist[s[i].zhong]+1)
35             {
36                 f=Shoot(s[i].zhong,min(s[i].flow,maxf)),
37                 maxf-=f,ret+=f,s[i].flow-=f,s[i^1].flow+=f;
38                 if(!maxf)return ret;
39             }
40         if(!(--gap[dist[rt]]))dist[S]=n+1;
41         ++gap[++dist[rt]],cur[rt]=adj[rt];
42         return ret;
43     }
44     inline int ISAP(int a,int b)
45     {
46         S=a,T=b;int maxf=0;bfs();
47         memcpy(cur,adj,sizeof(adj));
48         while(dist[S]<=n)maxf+=Shoot(S,inf);
49         return maxf;
50     }
51     inline void cut_off(int x)
52     {
53         register int i;
54         for(i=adj[x];i;i=s[i].next)
55             s[i].flow=s[i^1].flow=0;
56     }
57     inline void get_ans(int a,int b,int ss,int tt)
58     {
59         add(b,a,inf),add(a,b,0),ISAP(ss,tt);
60         int ans=s[e].flow;
61         s[e].flow=s[e^1].flow=0;
62         cut_off(ss),cut_off(tt);
63         printf("%d\n",ans-ISAP(b,a));
64     }
65 }SAP;
66 int n,m,S,T,SS,TT;
67 int rudu[N],chudu[N],du[N];
68 int main()
69 {
70     scanf("%d",&n),S=0,T=n+1,SS=T+1,TT=SS+1;
71     SAP.intn(TT+1);
72     register int a,b,i,j;
73     for(i=1;i<=n;++i)
74         for(scanf("%d",&a),j=1;j<=a;++j)
75             scanf("%d",&b),++du[b],--du[i],
76             ++chudu[i],++rudu[b],
77             SAP.add(i,b,inf),SAP.add(b,i,0);
78     for(i=1;i<=n;++i)
79     {
80         if(!rudu[i])SAP.add(S,i,inf),SAP.add(i,S,0);
81         if(!chudu[i])SAP.add(i,T,inf),SAP.add(T,i,0);
82     }
83     for(i=1;i<=n;++i)
84     {
85         if(du[i]>0)SAP.add(SS,i,du[i]),SAP.add(i,SS,0);
86         if(du[i]<0)SAP.add(i,TT,-du[i]),SAP.add(TT,i,0);
87     }
88     SAP.get_ans(S,T,SS,TT);
89 }
时间: 2024-10-13 02:29:52

[BZOJ2502]清理雪道 有上下界网络流(最小流)的相关文章

P4843 清理雪道(上下界网络流)

P4843 清理雪道 上下界最小流 我们先搞一遍上下界可行流(转) 回忆上下界最大流的写法:在可行流的残量网络$s\ -\ t$上跑最大流,答案为可行流$+$残量网络的最大流 那么上下界最小流的写法呢? 只要在残量网络$t\ -\ s$上跑最大流,答案就是可行流$-$残量网络$t\ -\ s$的最大流辣 #include<iostream> #include<cstdio> #include<cstring> #include<queue> using na

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

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

BZOJ 2502: 清理雪道 | 有上下界最小流

#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define N 405 #define INF 0x3f3f3f3f #define M 200005 using namespace std; int head[N],cur[N],n,m,S,T,d[N],s,t,sum,ecnt=1,lev[N],ans,dec; queue<int> q; st

sgu 176 上下界网络流最小可行流带输出方案

算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再跑一遍超级源汇之间的最大流,p的流量就是我们要求的最小可行流流量(等于其反向边的"容量") 收获: 1. 最大可行流和最小可行流,当我们把其残量网络求出来后,其流量就是dst->src的残量. 每条边在此时的流量 = 流量下界 + 转换后对应边的流量 1 #include <c

bzoj 2406 二分+有源有汇上下界网络流可行流判定

弱爆了,典型的行列建模方式,居然想不到,题做少了,总结少了...... 二分答案mid s----------------------->i行----------------------->j列----------------------------->t [si-mid,si+mid]                  [L,R]                 [s[j]-mid,s[j]+mid] 即对每一行建一个点,每一列建一个点,用边来表示某一行某一列上的东西. 这种建模方式一

sgu 194 上下界网络流可行流判定+输出可行流

1 #include <cstdio> 2 #include <cstring> 3 #define min(a,b) ((a)<(b)?(a):(b)) 4 #define oo 0x3f3f3f3f 5 #define N 210 6 #define M 100010 7 8 struct Dinic { 9 int n, src, dst; 10 int head[N], dest[M], flow[M], eid[M], next[M], etot; 11 int c

有上下界的最大流解法

问题模型: 给定一个加权的有向图,满足: (1)容量限制条件: (2)流量平衡条件: (2)中的即除了源汇外,所有点都满足流量平衡条件,则称G为有源汇网络:否则,即不存在源汇,所有点都满足流量平衡条件,则称G为无源汇网络. 将这类问题由易到难一一解决: 问题[1] 求无源汇的网络有上下界的可行流 由于下界是一条弧上的流必需要满足的确定值.下面引入必要弧的概念:必要弧是一定流要满的弧.必要弧的构造,将容量下界的限制分离开了,从而构造了一个没有下界的网络G': 1. 将原弧(u,v)分离出一条必要弧

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

滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部.从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道. 由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务. 题意就是给定一张DAG,求每条边起码经过一次求覆盖所有边的最小路径条数

@总结 - 8@ 上下界网络流等一类网络流问题

目录 @0 - 参考资料@ @1 - 问题引入@ @2 - 上下界可行流@ @3 - 上下界最大流/最小流@ @4 - 上下界费用流@ @5 - 带负环的最小费用流@ @6 - 例题与参考代码实现@ @7 - 一些类似的杂题@ @0 - 参考资料@ menci 的博客 liu_runda 的博客 @1 - 问题引入@ 我们知道,通常情况下,一个合法的流应该具有如下几个性质: (1)(除源点汇点以外)流量守恒:\(\sum f(i, u) = \sum f(u, j)\). (2)斜对称性:\(f