链表结构,将每个点x出发的邻边链起来,用hd[x]记录每个条边的编号,说明这些边号是与x相关的。
链表:
原型:
struct P{
int to,nxt,dis;
}line[MAXM]//如果是无向图,数组大小为MAXN*2
初始化:
memset(hd,0,sieof hd);
num=0;
添加:
void add(int x,int y,int z){//x到y有距离为z的单向边(数列前向星)
num++;
line[num].dis = z;
line[num].nxt = hd[x];
line[num].to = y;
hd[x]=num;
}
遍历:
for(int i=hd[u];i!=-1;i=line[i].nxt){
...
}
dl.push(...);
...=dl.top();
dl.pop();
dl.empty();
dl.size();
#include<queue>
#include<iostream>
#include<cstdio>
using namespace std;
priority_queue <int> q;
int x;
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
q.push(x);
}
for(int i=1;i<=n;i++){
printf("%d ",q.top());
q.pop();
}
}
4.大变小
priority_queue<int,vector<int>,greater<int> > dl;
0
bool operator < (const Node& x)const{
return dis > x.dis;
}
1.基于贪心的想法
2.以1为起点,所有点当中一定至少可以确定一条最短路,即这条最短路不会被其他点再次更新。
3.之后又会诞生至少一条最短路,用其更新别的点,此后所有边中一定又会诞生出一条最短路
4.以此类推
因为每次都找已经是最短路的点,考虑用堆实现,o(n)->o(logn)
每次找已经是最短路的一点,去更新他点(松弛)
但是考虑一个点会被多次更新,入堆,因此堆中会存留不是最短路的点。而这个点一旦松弛完别人它的使命就结束了。堆中他的 “余党”就不能松弛别人了。
#include<bits/stdc++.h>
using namespace std;
int num;
int n,m,s;
int x,y,z;
int dis[100005],vis[100005];
int hd[100005];
struct P{
int dis,to,nxt;
}line[200005];
void add(int x,int y,int z){
num++;
line[num].dis =z;
line[num].nxt =hd[x];
line[num].to =y;
hd[x]=num;
}
struct Node{
int id,dis;
bool operator < (const Node& x)const{
return dis > x.dis ;
}
Node(){}
Node(int x,int y){id=x,dis=y;}
};
priority_queue<Node> dl;
void dij(){
while(!dl.empty()){
Node l=dl.top();
dl.pop();
int u=l.id ,v=l.dis ;
if(vis[u])continue;
vis[u]=1;
for(int i=hd[u];i!=-1;i=line[i].nxt ){
if(dis[line[i].to ]>dis[u]+line[i].dis ){
dis[line[i].to ]=dis[u]+line[i].dis;
dl.push(Node(line[i].to ,dis[line[i].to ]));
}
}
}
}
int main() {
cin>>n>>m>>s;
memset(hd,-1,sizeof hd);
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
add(x,y,z);
}
memset(dis,0x3f,sizeof dis);
dis[s]=0;
dl.push(Node(s,0));
dij();
for(int i=1;i<=n;i++){
cout<<dis[i]<<' ';
}
return 0;
}