一、题目:

二、题解:
1、通过数据我们发现,朴素的
0
0
0(n2)Dijkstra无法解决问题,因此我们可以采用优先队列来进行优化

2、我们发现朴素Dijk算法中,寻找最小点采用了0(n)
ll temp=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j] &&((temp==-1)||(dis[j]<dis[temp])))
{
temp=j;
}
}
这是非常没有必要的,因此我们可以想到维护一个小根堆,每次从堆中取出最小值,来简化时间复杂度.
2.1 重写priority_queue()比较函数
- 在
p
r
i
pri
pri中,我们规定先比较两个点的权重
- 当权重相同时,再比较点数下标大小
- 注意
p
r
i
pri
pri是使用
<
来维护一个大根堆
,因此要写成小根堆
时要重写<为大于号
struct node{
ll v;
ll w;
bool operator <(const node& u)const
{
return w==u.w ? v<u.v : w>u.w;
}
};
2.2、其他思路与朴素基本一致,详细代码如下:
void dijkstra(ll x)
{
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
priority_queue<node>pq;
pq.push({x,dis[x]});
while(pq.size())
{
int temp=pq.top().v;pq.pop();
if(vis[temp]) continue;
vis[temp]=true;
for(auto t:g[temp])
{
int y=t.v;
int w=t.w;
if(!vis[y] && dis[y]>dis[temp]+w)
{
dis[y]=dis[temp]+w;
pq.push({y,dis[y]});
}
}
}
}
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
struct node{
ll v;
ll w;
bool operator <(const node& u)const
{
return w==u.w ? v<u.v : w>u.w;
}
};
ll n,m;
vector<node>g[N];
bool vis[N];
ll dis[N];
void dijkstra(ll x)
{
memset(dis,0x3f,sizeof(dis));
dis[x]=0;
priority_queue<node>pq;
pq.push({x,dis[x]});
while(pq.size())
{
int temp=pq.top().v;pq.pop();
if(vis[temp]) continue;
vis[temp]=true;
for(auto t:g[temp])
{
int y=t.v;
int w=t.w;
if(!vis[y] && dis[y]>dis[temp]+w)
{
dis[y]=dis[temp]+w;
pq.push({y,dis[y]});
}
}
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int ui,vi,wi;cin>>ui>>vi>>wi;
g[ui].push_back({vi,wi});
}
dijkstra(1);
if (dis[n] >= 0x3f3f3f3f) {
cout << -1 << '\n';
} else {
cout << dis[n] << '\n';
}
return 0;
}