最近要准备PAT的考试了,所以总结一下算法的模板什么的。并且规范一下自己的代码。
迪杰斯特拉c++模板
原理
原理我就不赘述了,大伙自行到别处看看,大概理解来说就是分为两个阵容。
第一个阵容设为u,第二个阵容设为v。//可以用visit[]来区别这两个阵容
每次将v中离节点最近的push入u,然后更新v中离节点的距离,用以下公式更新:
d
i
s
t
[
v
i
]
=
d
i
s
t
[
u
i
]
+
e
[
u
i
]
[
v
i
]
dist[v_i]=dist[u_i]+e[u_i][v_i]
dist[vi]=dist[ui]+e[ui][vi]
因为每次都是将距离最近的push进入u,所以可以保证不用更新u里面的数值。
作用
设一个源节点为v,可以求得每个节点离v最近的距离。
要使用的数据
#define MAX 999999
visit[n]//用来判断是否访问,初始设置为0
e[n][n]//用来存储邻接矩阵,假如两个节点不相邻那么就设置其值为MAX
dist[n]//表示离v的距离,初始设值为MAX
代码模板
int e[][],dist[],visit[];
dist[c]=0;//这样可以保证从初始节点开始
while(1){
int min=MAX,index=-1;
for(int j=0;j<n;++j){
if(dist[j]<min && !visit[j]) min=dist[j],index=j;//找到最小的
}
if(index==-1) break;//说明全部已经push进去,不连通的节点除外
visit[index]=true;//将其值设置为真
for(int j=0;j<n;++j){
if(!visit[j] && e[index][j]!=MAX){
if(dist[index]+e[index][j]<dist[j]) dist[j]=dist[index]+e[index][j];//更新值
}
}
}
关于最小路径(不是值)
类似于并查集的思想,即每次更新的时候给更新的点加一个爸爸。
可以用
p
r
e
[
]
pre[]
pre[]或者
f
a
t
h
e
r
[
]
father[]
father[]来表示。可以放心的是因为每个值都是会被更新的不用担心有点不被更新到,除非是连通图外的点!
int e[][],dist[],visit[],father[];
dist[c]=0;//这样可以保证从初始节点开始
father[c]=0;
while(1){
int min=MAX,index=-1;
for(int j=0;j<n;++j){
if(dist[j]<min && !visit[j]) min=dist[j],index=j;//找到最小的
}
if(index==-1) break;//说明全部已经push进去,不连通的节点除外
visit[index]=true;//将其值设置为真
for(int j=0;j<n;++j){
if(!visit[j] && e[index][j]!=MAX){
if(dist[index]+e[index][j]<dist[j]){
dist[j]=dist[index]+e[index][j];//更新值
father[j]=farher[index];//更新父节点
}
}
}
}
1003 Emergency
PAT的一道题,写得挺乱的(指数据的定义方面)。这道题是迪杰斯特拉的应用,大概是让你求最小路径,并且再那么多相等的最小路径中你得算出其中点权最大的,path[]存人数(用w[]来定义好点),count[]存最小路径个数
然后同样是先初始源节点的值,然count是<时候更新,path是=时候更新。
- 更新值:
- 如果是小于的情况
最小距离更新,最小路径个数更新就是源的最小路径个数,即count[index]=count[j],人数就是源的人数加上该城市的人数 - 如果是等于的情况
就是到这点有相同的最小距离了,所以最小路径的个数是原先的最小路径个数加上源的最小路径个数:count[j]+=count[index],然年最大人数进行比较更新。
#include <bits/stdc++.h>
#define MAX 999999
using namespace std;
int main()
{
//迪杰斯特拉
int num[500]={0};//每个城市的人数
int matrix[500][500],dist[500],visit[500],count[500],path[500]; //path存人数。count存最小路径个数
int n,m,c1,c2,a,b,x;
cin>>n>>m>>c1>>c2;
for(int i=0;i<n;++i) cin>>num[i];
for(int i=0;i<n;++i) for(int j=0;j<n;++j){
if(i==j) matrix[i][j]=0;
else matrix[i][j]=MAX;
}
while(m--){
cin>>a>>b>>x;
matrix[a][b]=x;
matrix[b][a]=x;
}
for(int i=0;i<n;++i) dist[i]=MAX,visit[i]=0;
path[c1]=num[c1];
count[c1]=1;
dist[c1]=0;
while(1){
int min=MAX;
int index=-1;
for(int j=0;j<n;++j){
if(dist[j]<min && !visit[j]) min=dist[j],index=j;
}//找到最小的
if(index==-1) break;//没找到就break
visit[index]=true;
for(int j=0;j<n;++j){
if(!visit[j] && matrix[j][index]!=MAX){
if(dist[index]+matrix[index][j]<dist[j]){
dist[j]=dist[index]+matrix[index][j];
count[j]=count[index];
path[j]=path[index]+num[j];
}
else if(dist[index]+matrix[index][j]==dist[j]){
count[j]=count[j]+count[index];
if(path[index]+num[j]>path[j]) path[j]=path[index]+num[j];
}
}
}
}
printf("%d %d",count[c2],path[c2]);
}