[BZOJ2502]清理雪道

试题描述

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

输入

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

输出

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

输入示例


输出示例


数据规模及约定

见“输入”

题解

最小费用流。从源点向入度为 0 的点连容量无穷费用为 0 的有向边,从出度为 0 的点向汇点连容量无穷费用为 0 的有向边;然后对于这张 DAG 的每条有向边,拆分成两条同方向的有向边,一条容量为 1 费用负无穷,另一条容量无穷费用为 0. 因为我们需要强制每条边至少经过一次,所以要将其中一条的费用设成负无穷。

跑一边最小费用流(注意不是最大流)即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 110
#define maxm 40010
#define oo 2147483647
#define inf 100000
#define LL long long
struct Edge { int from, to, flow, cost; } ;
struct ZKW {
int n, m, s, t, head[maxn], next[maxm];
LL cost, ans;
Edge es[maxm];
bool inq[maxn];
LL d[maxn];
bool vis[maxn];
void init(int nn) {
n = nn; m = 0; memset(head, -1, sizeof(head));
return ;
}
void AddEdge(int a, int b, int c, int d) {
es[m] = (Edge){ a, b, c, d }; next[m] = head[a]; head[a] = m++;
es[m] = (Edge){ b, a, 0, -d }; next[m] = head[b]; head[b] = m++;
return ;
}
bool BFS() {
memset(inq, 0, sizeof(inq));
for(int i = 1; i <= n; i++) d[i] = oo;
deque <int> Q;
Q.push_front(t); inq[t] = 1; d[t] = 0;
while(!Q.empty()) {
int u = Q.front(); Q.pop_front(); inq[u] = 0;
for(int i = head[u]; i != -1; i = next[i]) {
Edge& e = es[i^1];
if(e.flow && d[e.from] > d[u] + e.cost) {
d[e.from] = d[u] + e.cost;
if(!inq[e.from]) {
inq[e.from] = 1;
if(Q.empty() || d[e.from] <= d[Q.front()]) Q.push_front(e.from);
else Q.push_back(e.from);
}
}
}
}
if(d[s] == oo) return 0;
for(int i = 0; i < m; i++) es[i].cost += d[es[i].to] - d[es[i].from];
cost += d[s];
return 1;
}
int DFS(int u, int a) {
if(u == t || !a){ ans += cost * a; return a; }
vis[u] = 1;
int flow = 0, f;
for(int i = head[u]; i != -1; i = next[i]) {
Edge& e = es[i];
if(!vis[e.to] && e.flow && !e.cost && (f = DFS(e.to, min(a, e.flow)))) {
a -= f; flow += f;
e.flow -= f; es[i^1].flow += f;
if(!a) return flow;
}
}
return flow;
}
int MaxFlow(int ss, int tt) {
s = ss; t = tt;
int flow = 0, tmp;
while(BFS()) {
if(cost >= 0) break;
do {
memset(vis, 0, sizeof(vis));
tmp = DFS(s, oo);
flow += tmp;
} while(tmp);
}
return flow;
}
} sol; int in[maxn], out[maxn];
int main() {
int n = read(), s = n + 1, t = s + 1;
sol.init(n + 2);
for(int i = 1; i <= n; i++) {
int m = read();
while(m--) {
int a = read();
in[a]++; out[i]++;
sol.AddEdge(i, a, 1, -inf);
sol.AddEdge(i, a, oo, 0);
}
}
for(int i = 1; i <= n; i++) {
if(!in[i]) sol.AddEdge(s, i, oo, 0);
if(!out[i]) sol.AddEdge(i, t, oo, 0);
} printf("%d\n", sol.MaxFlow(s, t)); return 0;
}

[BZOJ2502]清理雪道的更多相关文章

  1. BZOJ2502:清理雪道(有上下界最小流)

    Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时 ...

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

    2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MB Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场 ...

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

    滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞 ...

  4. 【上下界网络流】bzoj2502: 清理雪道

    模型:无源汇有上下界可行流 LJN:模板题吧 Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的 ...

  5. 洛谷4843 BZOJ2502 清理雪道

    有源汇有上下界的最小可行流. YY一下建图应该很好搞吧(? 就是对于每个雪道都是[1,inf]然后源点到所有点都是[0,inf]所有点到汇点都是[0,inf] 这样的话跑一个有源汇上下界最小可行流就可 ...

  6. bzoj2502: 清理雪道(有源汇有上下界最小流)

    传送门 别说话,自己看,我不会->这里 我这里用的建图方法是先跑一次最大流,连上$(t,s,inf)$之后再跑一遍,然后答案就是之前连的那条边的反向边的流量 据说还有种方法是连上$(t,s,in ...

  7. bzoj2502清理雪道

    传送门 好题啊,由于每个点既可以进,也可以出,就可以新建一个源点和汇点,对于每个点都连边,然后就是最小流板子了. 代码: #include<cstdio> #include<iost ...

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

    bzoj状态里有两种,一种时间是个位数,一种是四位数,我就是四位数的那种,,,估计都是看了hzwer.. #include <bits/stdc++.h> #define INF 0x3f ...

  9. 【BZOJ2502】清理雪道 有上下界的网络流 最小流

    [BZOJ2502]清理雪道 Description        滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降 ...

随机推荐

  1. Linux下硬盘安装Windows系统。

    注意:本方法安装后会把Linux系统损坏,方法适用于完全不再需要Linux系统. 本方法在ubuntu 14.04,centos 6.5,debian 8测试成功. 安装方法是通过grub2引导Win ...

  2. 配置域从DNS服务器以及缓存DNS服务器

    一.域从DNS服务器的作用 我们在之前上一篇随笔里有提到,DNS服务器一般有三种类型,一个是Primary DNS Server(主DNS服务器),一个是Secondary DNS Server(从D ...

  3. 【ELK Stack】ELK+KafKa开发集群环境搭建

    部署视图 运行环境 CentOS 6.7 x64 (2核4G,硬盘100G) 需要的安装包 Runtime jdk1.8 : jdk-8u91-linux-x64.gz (http://www.ora ...

  4. 关于opacity透明度子元素继承现象的若干研究以及hack方法

    [感想]信息时代的信息是有时效性的,今天是确确实实感受到了.互联网资料虽然丰富,但是质量不一,还有大量的跟风雷同,很多人都是随手拷贝过来,根本没有实践.以前端为例,这两年浏览器的迅猛发展,造成很多原有 ...

  5. JavaScript、CSS、JSP 实现用户注册页面与信息校验

    参考:http://blog.csdn.net/fightfaith/article/details/50277337 需求:实现用户注册页面并作出逻辑校验.要求: (1)完成注册页面样式如下: (2 ...

  6. Fluent Ribbon项目出现“命名空间“clr-namespace:Fluent;assembly=Fluent”中不存在“RibbonWindow”名称”的解决方法

    之前在学习@aganqin的Fluent Ribbon项目(http://www.cnblogs.com/aganqin/p/3269384.html).但是一直都有引用了Fluent.dll后仍旧出 ...

  7. oracle-1

    使用sqlplus 进入oracle (1)服务的启动终止 oracle 服务的关闭: SQL> shutdown immediate; oracle服务的启动: SQL> startup ...

  8. 【kAriOJ】离散数学春季学期编程测试 1

    A.凯撒密码 题意: 给你k1,k2,和一串明文,一串密文. 明文用k1加密,密文用k2解密. 对于明文要把字母转换成大写字母,非字母全部删除. 额:要考虑到取模可能会变成负数,所以要加一下26再取模 ...

  9. DLX模型问题

    问题:sevenzero liked Warcraft very much, but he haven't practiced it for several years after being add ...

  10. Codevs2157 配对

    题目描述 Description 给出2个序列A={a[1],a[2],…,a[n]},B={b[1],b[2],…,b[n]},从A.B中各选出n个元素进行一一配对(可以不按照原来在序列中的顺序), ...