NWERC 2016 Problem I Iron and Coal Coal. (SPFA)

NWERC 2016

Problem I Iron and Coal Coal.

Photo by US Federal Government

There are many excellent strategy board games, and your favourite among them is called “Steel Age”. It offers many different paths to victory but you prefer the blood-and-fire-strategy: build as many soldiers as possible and club your opposition into submission. To be able to build soldiers you need two resources: iron ore and coal. The board consists of different cells numbered from 1 to n which can contain resources. The rules for moving from one cell to another are rather complicated: if you can move from cell A to cell B, it does not always mean that you can also move from B to A. For example, if two cells are connected by a river, then you may be able to move downstream, but not upstream, so long as you didn’t invent a steam engine; however, it still could be possible to reach the upstream cell by using roads and taking a detour over other cells. At the beginning of the game you own only one such cell, where all your settlers are located. At every move you are allowed to move an arbitrary number of settlers from a cell to one of its accessible neighbours. By moving your settlers into a cell for the first time, you “claim” it. Every claimed cell will bind one settler, which has to stay in this cell until the end of the game. However, there is no need to leave a settler in your initial cell because it is where your palace is located and thus the cell stays claimed for all time. Your goal is to claim at least one cell containing the resource “iron ore” and at least one cell with resource “coal” in order to be able to build soldiers. What is the minimal number of settlers you need to reach this goal? Input The input consists of: • One line with three integers n (2 ≤ n ≤ 105 ), the number of cells on the playing field, m (1 ≤ m < n), the number of cells containing iron ore, and k (1 ≤ k < n), the number of cells containing coal. • One line with m distinct integers o1, . . . , om (1 ≤ oi ≤ n for all 1 ≤ i ≤ m), where o1, . . . , om are the IDs of cells with iron ore. • One line with k distinct integers c1, . . . , ck (1 ≤ ci ≤ n for all 1 ≤ i ≤ k), where c1, . . . , ck are the IDs of cells with coal. • n lines describing the topology of the board. The j-th line of this block specifies the accessible neighbours of the j-th cell and consists of the following integers: – One integer 0 ≤ a ≤ 10, the number of cells accessible from cell j. – a distinct integers b1, . . . , ba (1 ≤ bi ≤ n, bi 6= j for all 1 ≤ i ≤ a), the IDs of the cells accessible from cell j. It is guaranteed, that no cell contains both resources, iron ore and coal. At the beginning of the game you own only the cell with ID 1. NWERC 2016 Problem I: Iron and Coal 17 NWERC 2016 Output Output the minimum number of settlers needed to claim at least one cell with coal and at least one cell with iron ore. Output “impossible” if it is impossible to own both, coal and iron ore. Sample Input 1 Sample Output 1 3 1 1 2 3 1 2 2 3 1 1 1 2 Sample Input 2 Sample Output 2 3 1 1 2 3 1 2 1 1 2 1 2 impossible NWERC 2016 Problem I: Iron and Coal 18

题意:从1号点出发,求找一个铁一个碳的最短路程。

题解:三遍SPFA,先反向建边第一次找到每个点到最近碳点的最短路,第二次找到每个点到最近铁点最短路。再正向建边,找到每个点到1号点的最短路。最后遍历每个点的三个距离dis1,dis2,dis3,找出最小值。

 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<algorithm>
#include<vector>

using namespace std;
const int MaxN = 2e6;
typedef long long LL;
typedef unsigned long long ULL;

int dis1[MaxN + 5],dis2[MaxN + 5],dis3[MaxN + 5],vis[MaxN + 5],pre[MaxN + 5],last[MaxN + 5],other[MaxN + 5],U[MaxN + 5],V[MaxN + 5],a[MaxN + 5],b[MaxN + 5];
queue<int>q;
int n,m,k,all,tot;
LL ans;

void Build(int y,int x){
	pre[++all] = last[x];
	last[x] = all;
	other[all] = y;
}

void SPFA1(){
	int now,ed,dr;
	for(int i = 1;i <= m;i++){
		vis[a[i]] = 1;
		dis1[a[i]] = 0;
		q.push(a[i]);
	}
	while(!q.empty()){
		now = q.front();
		ed = last[now];
		while(ed != -1){
			dr = other[ed];
			if(dis1[now] + 1 < dis1[dr]){
				dis1[dr] = dis1[now] + 1;
				if(!vis[dr]){
					vis[dr] = 1;
					q.push(dr);
				}
			}
			ed = pre[ed];
		}
		q.pop();
		vis[now] = 0;
	}
}

void SPFA2(){
	int now,ed,dr;
	for(int i = 1;i <= k;i++){
		vis[b[i]] = 1;
		dis2[b[i]] = 0;
		q.push(b[i]);
	}
	while(!q.empty()){
		now = q.front();
		ed = last[now];
		while(ed != -1){
			dr = other[ed];
			if(dis2[now] + 1 < dis2[dr]){
				dis2[dr] = dis2[now] + 1;
				if(!vis[dr]){
					vis[dr] = 1;
					q.push(dr);
				}
			}
			ed = pre[ed];
		}
		q.pop();
		vis[now] = 0;
	}
}

void SPFA3(){
	int now,ed,dr;
	vis[1] = 1;
	q.push(1);
	dis3[1] = 0;
	while(!q.empty()){
		now = q.front();
		ed = last[now];
		while(ed != -1){
			dr = other[ed];
			if(dis3[now] + 1 < dis3[dr]){
				dis3[dr] = dis3[now] + 1;
				if(!vis[dr]){
					vis[dr] = 1;
					q.push(dr);
				}
			}
			ed = pre[ed];
		}
		q.pop();
		vis[now] = 0;
	}
}



int main(){
	ans = 2000000000LL;
	tot = 0;
	all = -1;
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 1;i <= 1e6+5;i++)last[i] = -1;
	for(int i =0;i <= n;i++){
		dis1[i] = 2000000000LL;
		dis2[i] = 2000000000LL;
		dis3[i] = 2000000000LL;
	}
	for(int i = 1;i <= m;i++)scanf("%d",&a[i]);
	for(int i = 1;i <= k;i++)scanf("%d",&b[i]);
	int u ,v;
	for(int i = 1;i <= n;i++){
		scanf("%d",&u);
		for(int j = 1;j <= u;j++){
			scanf("%d",&v);
			Build(i,v);
			U[++tot] = v;
			V[tot] = i;
		}
	}
	SPFA1();
	SPFA2();
	for(int i = 0;i <= all;i++){
		pre[i] = 0;
		other[i] = 0;
	}
	for(int i = 1;i <= n;i++)last[i] = -1;
	all = -1;
	for(int i = 1;i <= tot ;i++)Build(U[i],V[i]);
	SPFA3();
	for(int i = 1;i <= n;i++){
		ans = min(ans,((LL)dis1[i] + (LL)dis2[i] + (LL)dis3[i]));
	}
	if(ans == 2000000000LL)printf("impossible\n");
	else printf("%d\n",(int)ans);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值