ybtoj·高效生产【SPFA】

Description–

> l i n k link link

产品要从 A 部门运到 B 部门时,都要先从 A 部门送到质量检验处,检验合格后再从质量检验处运到 B 部门

有些部门之间有传送带连接,厂长想知道每次将产品从一个部门运送到另一个部门最少需要多长时间


Input–

第一行两个整数 n , m n ,m n,m n n n表示部门数量, m m m 表示传送带数量。出于方便, 1 1 1 号部门是质量检验处。
接下来 m m m 行,每行三个整数 u , v , w u,v,w u,v,w,表示有一条从 u u u 部门到 v v v 部门的传送带,传送过去需要 w w w 个单位时间,传送带是单向的。
接下来一个整数 q q q,表示有 q q q 次运送。
接下来 q q q 行,每行两个数 a , b a,b a,b,表示这一次要将产品从 a a a 部门运送到 b b b 部门。

Output–

输出 q q q 行,每行一个整数,表示这次运送最少需要的时间。若没有传送方案,输出 − 1 -1 1


Sample Input–

5 5
1 2 3
1 3 5
4 1 7
5 4 1
5 3 1
3
4 2
5 3
2 3

Sample Output–

10
13
-1

说明–

在这里插入图片描述


解题思路–

正向跑一遍关于点“1”的spfa(“1”到某点)
再反正向跑一遍关于点“1”的spfa(某点到“1”)


代码–

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

queue <int> q;

int n, m, x, y, z, u, t, qq;
int lsa[3100], lsb[3100], disa[3100], disb[3100];
bool pd[3005];

struct ooo
{
	int to, w, next;
}a[110000], b[110000];

void sdf(int aa, int bb, int cc)
{
	a[++t] = (ooo){bb, cc, lsa[aa]}, lsa[aa] = t;
	b[t] = (ooo){aa, cc, lsb[bb]}, lsb[bb] = t;
}

void spfa()
{
	memset(disa, 0x7f, sizeof(disa));
	pd[1] = 1, q.push(1), disa[1] = 0;
	while (!q.empty())
	{
		u = q.front(), q.pop();
		for (int i = lsa[u]; i; i = a[i].next)
		  if (a[i].w + disa[u] < disa[a[i].to])
		  {
			  disa[a[i].to] = a[i].w + disa[u];
			  if (!pd[a[i].to])
			  {
			  	 pd[a[i].to] = 1;
			  	 q.push(a[i].to);
			  }
		  }
		pd[u] = 0;
	}
}//正

void spfa2()
{
	memset(disb, 0x7f, sizeof(disb));
	pd[1] = 1, q.push(1), disb[1] = 0;
	while (!q.empty())
	{
		u = q.front(), q.pop();
		for (int i = lsb[u]; i; i = b[i].next)
		  if (b[i].w + disb[u] < disb[b[i].to])
		  {
			  disb[b[i].to] = b[i].w + disb[u];
			  if (!pd[b[i].to])
			  {
			  	 pd[b[i].to] = 1;
			  	 q.push(b[i].to);
			  }
		  }
		pd[u] = 0;
	}
}//反

int main()
{
	//freopen("production.in", "r", stdin);
	//freopen("production.out", "w", stdout);
	
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; ++i)
	  scanf("%d%d%d", &x, &y, &z), sdf(x, y, z);
	spfa();
	spfa2();
	scanf("%d", &qq);
	for (int i = 1; i <= qq; ++i)
	{
		scanf("%d%d", &x, &y);
		if (disb[x] == disb[0] || disa[y] == disa[0])
	      printf("-1\n");
	    else printf("%d\n", disb[x] + disa[y]);
	}
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值