描述
给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值。
请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。
输入
第一行包含整数n和m。
接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
输出
输出一个整数,表示1号点到n号点的最短距离。
如果路径不存在,则输出-1。
输入样例
3 3
1 2 2
2 3 1
1 3 4
输出样例
3
代码实现
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
#define Inf 0x3f3f3f3f
const int N=150005;
typedef pair<int,int> PII;
typedef struct Enode* Arc;
struct Enode
{
Enode(int b=0,int c=0):y(b),z(c),next(NULL){}
int y,z;
Arc next;
};
Arc Ge[N];
int Dist[N]={0};
void Add(int x,Arc newnode)
{
if(Ge[x])
{
Arc temp=Ge[x];
while(temp->next)temp=temp->next;
temp->next=newnode;
}
else Ge[x]=newnode;
}
void Dijkstra(int);
int n,m;
int main()
{
for(int i=0;i<N;i++){Ge[i]=NULL;Dist[i]=Inf;}
cin>>n>>m;
for(int i=0;i<m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
if(x!=y)
{
Arc newnode=new Enode(y,z);
Add(x,newnode);
}
}
Dijkstra(1);
return 0;
}
void Dijkstra(int source)
{
priority_queue<PII,vector<PII>,greater<PII>> q;
//Dist[source]=0;
q.push({0,source});
while(!q.empty())
{
auto t=q.top();
q.pop();
int x=t.second;
int u=t.first;
if(Dist[x]<=u)continue;
else
{
Dist[x]=u;
Arc temp=Ge[x];
while(temp)
{
q.push({u+temp->z,temp->y});
temp=temp->next;
}
}
}
if(Dist[n]==Inf)cout<<-1<<endl;
else cout<<Dist[n]<<endl;
}
请注意priority_queue
是一种容器适配器,需要指定一个容器类型来存储队列中的元素,本题使用greater将队列q指定为一个最小堆。
priority_queue<ContainerValueType, Container, Compare>
这题我在编写时出了一个问题,当我尝试用自定义的结构体定义优先队列的排序规则时,以下情况会超时①。
struct Compare {
bool operator()(const PII& a, const PII& b) {
return a.first < b.first; // 比较pair的第一个元素
}
};
而改为以下形式②时,却可以通过测试点,那么是什么导致上一种代码测试点运行超时呢?
struct Compare {
bool operator()(const PII& a, const PII& b) {
return a.first > b.first; // 比较pair的第一个元素
}
};
于是我上网查了优先队列的资料,发现②形式才能实现最小堆,也就是说优先队列内部的逻辑应该如下。其中less为大堆,而Greater代表小堆。也就是说在定义优先队列数据结构<x,y>时,y的优先级高于x的优先级,注意与sort算法区分。
template <class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};