洛谷 P4779 【模板】单源最短路径(标准版)

题目

给定一个 n 个点,m 条有向边的带非负权图,请你计算从 s 出发,到每个点的距离。

输入格式

第一行为三个正整数 n,m,s。第二行起 m 行,每行三个非负整数 ui,vi,wi,表示从 ui 到 vi 有一条权值为 wi 的有向边。

输出格式

输出一行 n 个空格分隔的非负整数,表示 s 到每个点的距离。

输入输出样例

输入1

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出1

0 2 4 3

说明/提示

1 ≤ n ≤ 105

1 ≤ m ≤ 2×105

s = 1

1 ≤ ui , vi ≤ n

0 ≤ wi ≤ 109

0 ≤ ∑ wi ≤ 109

题解

思路

标准的Dijkstra,不解释(然而第一次做时不会用优先队列,所以爆零了)
值得一提的是,朴素Dijkstra的时间复杂度好像是 O( n2 ) ,而优先队列优化的时间复杂度好像是 O( m log m ),在选择优不优化时看清数据范围(即 m = n2 时,比如某道最小生成树题,以后应该会发)。
代码是以前写的,所以码风和变量名不忍直视,甚至还出现了一些我自己都看不懂的蜜汁操作(
不过由于情怀问题还是发上来吧(其实是因为不想重新写一遍),以后有时间再重写。

代码

O( n2 ):

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
using namespace std;
int n,m,s,dis[10001],first[10001],next[500001];
bool vis[10001];
struct st
{
    
    
	int s,f,jz;
}a[500001];
int main()
{
    
    
	memset(dis,-1,sizeof(dis));
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=m;i++)
	{
    
    
		scanf("%d%d%d",&a[i].s,&a[i].f,&a[i].jz);
		if(first[a[i].s]==0) first[a[i].s]=i;
		else
		{
    
    
			next[i]=first[a[i].s];
			first[a[i].s]=i;
		}
	}
	int p=first[s];
	while(p!=0)
	{
    
    
		if(dis[a[p].f]==-1) dis[a[p].f]=a[p].jz;
		else if(a[p].jz<dis[a[p].f]) dis[a[p].f]=a[p].jz;
		p=next[p];
	}
	dis[s]=0;
	dis[0]=2147483647;
	vis[s]=true;
	int sum;
	for(int i=2;i<=n;i++)
	{
    
    
		sum=0;
		for(int j=1;j<=n;j++) if(!vis[j]&&dis[j]!=-1&&dis[j]<=dis[sum]) sum=j;
		if(sum==0) break;
		vis[sum]=true;
		p=first[sum];
		while(p!=0)
		{
    
    
			if(dis[sum]+a[p].jz<dis[a[p].f]||dis[a[p].f]==-1) dis[a[p].f]=dis[sum]+a[p].jz;
			p=next[p];
		}
	}
	for(int i=1;i<=n;i++)
	{
    
    
		if(vis[i]) printf("%d ",dis[i]);
		else printf("2147483647 ");
	}
	return 0;
}

O( m log m ):

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<queue>
using namespace std;
#define N 999999999999999999
long long n,m,s,fi[100005],ne[200005],dis[100005],t;
bool vis[100005];
struct st
{
    
    
	long long s,f,jz;
}maap[200005];
struct no
{
    
    
	long long f,jz;
	bool operator < (const no &that) const
	{
    
    
		return jz>that.jz;
	}
}a;
priority_queue<no> q;
int main()
{
    
    
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=n;i++) dis[i]=N;
	for(int i=1;i<=m;i++)
	{
    
    
		scanf("%d%d%d",&maap[i].s,&maap[i].f,&maap[i].jz);
		ne[i]=fi[maap[i].s];
		fi[maap[i].s]=i;
	}
	a.f=s;
	a.jz=0;
	dis[s]=0;
	q.push(a);
	while(!q.empty())
	{
    
    
		while(!q.empty()&&vis[q.top().f]) q.pop();
		if(q.empty()) break;
		t=q.top().f;
		q.pop();
		vis[t]=true;
		t=fi[t];
		while(t!=0)
		{
    
    
			if(dis[maap[t].s]!=N&&dis[maap[t].f]>dis[maap[t].s]+maap[t].jz)
			{
    
    
				dis[maap[t].f]=dis[maap[t].s]+maap[t].jz;
				a.f=maap[t].f;
				a.jz=dis[maap[t].f];
				q.push(a);
			}
			t=ne[t];
		}
	}
	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/bmhkhtj/article/details/108751195