两道题很类似,可以放在一起理解
Dijstra+链式前向星存图+小根堆,模板
详解代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,s;
int head[100005],cnt,d[100005];
bool v[100005];
struct EDGE{
int next,to,w;
}edge[200005];
void add(int x,int y,int z){
cnt++;
edge[cnt].next=head[x];
edge[cnt].to=y;
head[x]=cnt;
edge[cnt].w=z;
}
struct node
{
int dis;
int pos;
bool operator <( const node &x )const
{
return x.dis < dis;
}
};
void dijstra(){
d[s]=0;
priority_queue<node> q;//小顶堆
q.push((node) {0,s});
while(!q.empty()){
node tmp=q.top();
q.pop();
int h=tmp.pos,len=tmp.dis;
if(v[h]) continue;
v[h]=1;
for(int i=head[h];i;i=edge[i].next){
int g=edge[i].to;
if(d[g] > d[h]+edge[i].w){
d[g]=d[h]+edge[i].w;
if(!v[g]){
q.push((node){d[g],g});
}
}
}
}
}
int main(){
cin>>n>>m>>s;
memset(d,0x3f,sizeof(d));
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
dijstra();
for( int i = 1; i <= n; i++ ) cout<<d[i]<<' ';
}
Dijstra+邻接表+小根堆
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = N * 3;
int n, m;
int head[N], to[M], w[M], ne[M],cnt;
int d[N];
bool v[N];
void add(int a, int b, int c){
cnt++;
to[cnt]=b;
ne[cnt]=head[a];
w[cnt]= c;
head[a]=cnt;
}
void dij(){
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> >> q;
q.push({0, 0});//距离,坐标
memset(d, 0x3f, sizeof d);
d[0]=0;
while(!q.empty()){
auto t = q.top();
q.pop();
int ver = t.second;
if (v[ver]) continue;
v[ver] = true;
for (int i = head[ver]; i; i = ne[i])
{
int j = to[i];
if (d[j] > d[ver] + w[i])
{
d[j] = d[ver] + w[i];
q.push({d[j], j});
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
scanf("%d", &m);
while (m -- )
{
int x;
scanf("%d", &x);
add(0, x, 0);//转化为单源路径问题,源点位编号为0的村庄
}
dij();
scanf("%d", &m);
while (m -- )
{
int x;
scanf("%d", &x);
printf("%d\n", d[x]);
}
}