题意:有一个有向图,有些点是煤,有些点是铁,但不会同时有铁和煤。现在我要从1出发,占领可以到达的点。问最少占领几个点能同时拥有一个煤和一个铁(1不用占领)。

思路:思路很秀啊。我们从1往外bfs,得到所有点到1的最短路dis[i][0],然后从所有煤跑bfs得到所有点到煤的最短路dis[i][1],我们再从所有铁跑bfs得到所有点到铁的最短路dis[i][2],那么dis[i][0] + dis[i][1] + dis[i][2]就是以i为分界点分别前往煤和铁的占领的最小距离。那么答案就是min{ dis[i][0] + dis[i][1] + dis[i][2] }。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int n, m, k;
int iron[maxn], coal[maxn], vis[maxn];
vector<int> G[maxn], g[maxn];
int dis[maxn][3];
struct node{
int x;
int step;
};
void bfs1(){
for(int i = 1; i <= n; i++) vis[i] = 0;
queue<node> q;
while(!q.empty()) q.pop();
vis[1] = 1;
dis[1][0] = 0;
node a, b;
a.x = 1, a.step = 0;
q.push(a);
while(!q.empty()){
a = q.front();
q.pop();
for(int i = 0; i < G[a.x].size(); i++){
int v = G[a.x][i];
if(vis[v]) continue;
vis[v] = 1;
dis[v][0] = a.step + 1;
b.x = v, b.step = a.step + 1;
q.push(b);
}
}
}
void bfs2(){
for(int i = 1; i <= n; i++) vis[i] = 0;
queue<node> q;
while(!q.empty()) q.pop();
node a, b;
for(int i = 1; i <= n; i++){
if(iron[i]){
vis[i] = 1;
dis[i][1] = 0;
a.x = i, a.step = 0;
q.push(a);
}
}
while(!q.empty()){
a = q.front();
q.pop();
for(int i = 0; i < g[a.x].size(); i++){
int v = g[a.x][i];
if(vis[v]) continue;
vis[v] = 1;
dis[v][1] = a.step + 1;
b.x = v, b.step = a.step + 1;
q.push(b);
}
}
}
void bfs3(){
for(int i = 1; i <= n; i++) vis[i] = 0;
queue<node> q;
while(!q.empty()) q.pop();
node a, b;
for(int i = 1; i <= n; i++){
if(coal[i]){
vis[i] = 1;
dis[i][2] = 0;
a.x = i, a.step = 0;
q.push(a);
}
}
while(!q.empty()){
a = q.front();
q.pop();
for(int i = 0; i < g[a.x].size(); i++){
int v = g[a.x][i];
if(vis[v]) continue;
vis[v] = 1;
dis[v][2] = a.step + 1;
b.x = v, b.step = a.step + 1;
q.push(b);
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++){
iron[i] = coal[i] = 0;
G[i].clear();
g[i].clear();
memset(dis[i], INF, sizeof(dis[i]));
}
for(int i = 1; i <= m; i++){
int u;
scanf("%d", &u);
iron[u] = 1;
}
for(int i = 1; i <= k; i++){
int u;
scanf("%d", &u);
coal[u] = 1;
}
for(int i = 1; i <= n; i++){
int p, u, v;
scanf("%d", &p);
u = i;
while(p--){
scanf("%d", &v);
G[u].push_back(v);
g[v].push_back(u);
}
}
bfs1();
bfs2();
bfs3();
int ans = INF;
for(int i = 1; i <= n; i++){
if(dis[i][0] == INF || dis[i][1] == INF || dis[i][2] == INF) continue;
ans = min(ans, dis[i][0] + dis[i][1] + dis[i][2]);
}
if(ans < INF) printf("%d\n", ans);
else printf("impossible\n");
return 0;
}

Gym 101170I Iron and Coal(BFS + 思维)题解的更多相关文章

  1. DFS/BFS+思维 HDOJ 5325 Crazy Bobo

    题目传送门 /* 题意:给一个树,节点上有权值,问最多能找出多少个点满足在树上是连通的并且按照权值排序后相邻的点 在树上的路径权值都小于这两个点 DFS/BFS+思维:按照权值的大小,从小的到大的连有 ...

  2. Gym 100971A Treasure Island BFS 思维题

    A - Treasure Island Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64 ...

  3. Gym - 101572D Distinctive Character bfs 思维

    题目传送门 题目大意: 给出n个01串,让你构造一个字符串,使这个字符串和这些字符串中相似程度最高 尽可能低.如果两个字符串对应位置相同,则相似程度加一. 思路: 每一个01串更改自己的一部分后,都可 ...

  4. Codeforces Gym101170I:Iron and Coal(建多幅图+多次BFS)***

    题目链接 题意 有n个点,其中有m个点是铁矿,k个点是煤,从1号点出发,你可以派一些士兵跑向不同的点,问占领至少一个铁矿和一个煤的时候,最少需要占领多少个点. 思路 建两幅图,其中一幅是正向边,一幅是 ...

  5. Codeforces Gym 100187E E. Two Labyrinths bfs

    E. Two Labyrinths Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/prob ...

  6. Gym - 100187E E - Two Labyrinths —— bfs

    题目链接:http://codeforces.com/gym/100187/problem/E 题解:一开始做的时候是将两幅图合并,然后直接bfs看是否能到达终点.但这种做法的错的,因为走出来的路对于 ...

  7. ACM: Gym 101047E Escape from Ayutthaya - BFS

    Gym 101047E Escape from Ayutthaya Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I6 ...

  8. Gym 101617J Treasure Map(bfs暴力)

    http://codeforces.com/gym/101617/attachments 题意:给出一个图,每个顶点代表一个金矿,每个金矿有g和d两个值,g代表金矿初始的金子量,d是该金矿每天的金子量 ...

  9. 逃离迷宫(BFS)题解

    Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有 ...

随机推荐

  1. Ubuntu源、Python虚拟环境及pip源配置

    Ubuntu 命令行更改源 在修改source.list前,最好先备份一份 软件源的地址配置文件在 /etc/apt/sources.list 执行备份命令 sudo cp /etc/apt/sour ...

  2. vue、element-ui 后台菜单切换重新请求数据

    我们在做后台管理系统时,通常将数据请求挂载到created或mounted钩子中,但这样引发的问题是它只会被出发一次,如果不同菜单中数据关联性较大,切换过程中未及时更新数据,容易引发一些问题,这种情况 ...

  3. linux静态库

    库文件可以理解为别人写好的现成的代码,但是看不见源码,只提供程序入口.库又分为动态库和静态库,静态库是在编译的时候将库编译进可执行程序中,运行时不再依赖库文件,而动态库是在运行时加载,运行时需要依赖库 ...

  4. Linux 三剑客之 grep 使用详解

    Linux 最重要的三个命令在业界被称为三剑客,它们是:awk.sed.grep.sed 已经在上篇中讲过,本文要讲的是 grep 命令. 我们在使用 Linux 系统中,grep 命令的使用尤为频繁 ...

  5. C#高级编程第11版 - 第三章 索引

    [1]3.1 创建及使用类 1.构造函数:构造函数的名字与类名相同: 使用 new 表达式创建类的对象或者结构(例如int)时,会调用其构造函数.并且通常初始化新对象的数据成员. 除非类是静态的,否则 ...

  6. 浅析Linux用户空间中的Mmap

    一.MMap基础概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.实现这样的映射关系后,进程就可以采 ...

  7. 题解 UVA11694 【Gokigen Naname谜题 Gokigen Naname】

    题目 题解 考场上连暴力都不会打的码农题,深搜是真的难 /kk 前置问题 怎么输出"\" cout<<"\\"; 2.怎么处理不在一个环里,可以考虑 ...

  8. LOJ2436

    题目描述 幼儿园里有 N 个小朋友, lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于 ...

  9. Spark练习之创建RDD(集合、本地文件),RDD持久化及RDD持久化策略

    Spark练习之创建RDD(集合.本地文件) 一.创建RDD 二.并行化集合创建RDD 2.1 Java并行创建RDD--计算1-10的累加和 2.2 Scala并行创建RDD--计算1-10的累加和 ...

  10. Spring cloud-Bus (消息总线)

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring ...