题目
给定一个 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;
}