1399. 坐船旅行

1399. 坐船旅行

题目描述
NOIP有N个岛屿,编号为1…N,NOIP决定在岛屿之间发展船运网络。,

你在船运票务中心工作,很多人想花尽量少的钱从一个岛到另一个岛进行坐船旅行,他们每个人都报上自己的出发地和目的地,你的任务是告诉他最小花费。

但是在这个过程中船的航线不会一直不变,可能会在某个时候增加一些航线,这些新增加的航线显然对之前的询问没有作用,但对之后的询问就要考虑到这些航线了。

按照时间先后的顺序给你一个清单,里面包含询问以及增加航线的信息,写一个程序回答游客提出的问题。

输入
第1行:两个数 N(1<=N<=100) 和 k(1<=k<=5000),分别表示岛屿的数量以及清单的长度。
下面K行描述清单内容,有两种:
(1)格式为0 a b(1<=a<=n,1<=b<=n,a<>b)表示游客询问岛a到岛b的最小费用;
(2)1 a b e(1<=a,b<=n,a<>b,1<=e<=1000000)表示在a到b之间新增一条航线,费用为e,注意航线都是双向的。
一开始,没有任何航线,并且总的航线数不超过1000,两个岛之间可能有多条航线。

输出
对于每个询问输出对应的最小费用。

样例输入
样例输入1:

3 8
1 3 1 10
0 2 3
1 2 3 20
1 1 2 5
0 3 2
1 1 3 7
1 2 1 9
0 2 3

样例输入2:

5 16
1 1 2 343750
1 1 3 3343
1 1 4 347392
1 1 5 5497
1 2 3 123394
1 2 4 545492
1 2 5 458
1 3 4 343983
1 3 5 843468
1 4 5 15934
0 2 1
0 4 1
0 3 2
0 4 2
0 4 3
0 5 3

样例输出
样例输出1:

-1
15
12

样例输出2:

5955
21431
9298
16392
24774
8840

数据范围限制
提示

在这里插入图片描述
思路:
我们对于这么大的值,并且是最短路,那第一时间就想到了spfa。但是呢,题目说明对于每两个点之间可能会有多条路,如何去一条最短的呢?

其实我们只需用一个数组来记录以前的值,最后每想加路时,都需做一个比较,然后就解决了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
struct node
{
	int x,y,next,z;
} edge[10010];
int n,k,tot,hd[10010],q[10010],minn[10010],jl[110][110]; 
bool f[10010];
void add(int u,int v,int w)
{
	if(jl[u][v]) edge[jl[u][v]].z=edge[jl[v][u]].z=min(edge[jl[u][v]].z,w);
	else
	{
		edge[++tot].x=u;
		edge[tot].y=v;
		edge[tot].z=w;
		edge[tot].next=hd[u];
		hd[u]=tot;
		jl[u][v]=tot;	
	}
}
void spfa(int s) 
{
	memset(minn,127/3,sizeof(minn));
	f[s]=1,q[1]=s,minn[s]=0;
	int head=0,tail=1;
	while(head<=tail)
	{
		head++;
		int tx=q[head];
		for(int i=hd[tx];i;i=edge[i].next)
		{
			if(minn[edge[i].y]>minn[tx]+edge[i].z)
			{
				minn[edge[i].y]=minn[tx]+edge[i].z;
				if(!f[edge[i].y])
					f[edge[i].y]=1,q[++tail]=edge[i].y;
			}
		}
		f[tx]=0;
	}
}
int main()
{
	//fre();
	scanf("%d%d",&n,&k);
	for(int i=1;i<=k;i++)
	{
		int k,u,v,w;
		scanf("%d",&k);
		if(k) scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
		else if(!k) 
		{
			scanf("%d%d",&u,&v);
			spfa(u);
			if(minn[v]==707406378) printf("-1\n");
			else printf("%d\n",minn[v]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bigwinner888/article/details/106738446
今日推荐