代碼:
#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<set>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF=2147483647;
const int MM=500002;
const int NM=10002;
int n,m,s;//點,邊,起始
int dis[NM];//最小距離
bool book[NM];//記錄有沒有作為頂點搜尋過
//鍊式向前星
struct NODE{
int to;
int nxt;
int c;
}node[MM];//鍊式向前星
int head[NM],lcnt=1;
void add(int a,int b,int c){
node[lcnt].to=b;
node[lcnt].c=c;
node[lcnt].nxt=head[a];
head[a]=lcnt++;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>s;
for(int i=1;i<=n;i++){
dis[i]=INF;
}
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
//if(a==b)
// continue;
add(a,b,c);
//add(b,a,c);
}
for(int i=head[s];i;i=node[i].nxt){ //從起始點開始枚舉
int idx=node[i].to;
dis[idx]=min(node[i].c,dis[idx]); //更新最短路
}
dis[s]=0; //自身距離為0
book[s]=1; //标記搜尋過
for(int kkk=1;kkk<n;kkk++){ //枚舉每個點(用編号)
int minn=INF,u=0;
for(int i=1;i<=n;i++){
if(!book[i]&&dis[i]<minn){
u=i; //枚舉每個已經被标記了但是沒有被搜尋過的點
minn=dis[i]; //找距離最小的
}
}
/*for(int i=1;i<=n;i++){
if(mp[u][i]<INF){
dis[i]=min(dis[i],dis[u]+mp[u][i]);
}
}*/
for(int i=head[u];i;i=node[i].nxt){
int idx=node[i].to; //正在搜尋的點開始,枚舉每一條邊
dis[idx]=min(dis[idx],dis[u]+node[i].c); //更新最短距離,設f[i][j]為i到j的最大距離,d[i]為起始點到i的距離
//得到 d[j]=min(d[j],d[i]+f[i][j])
}
book[u]=1; //标記這個點搜尋過了
}
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
return 0;
}
檢視神奇代碼
1.儲存方式:
鍊式向前星>> https://www.cnblogs.com/dudujerry/p/9915713.html
int n,m,s;//點,邊,起始
int dis[NM];//最小距離
bool book[NM];//記錄有沒有作為頂點搜尋過
//鍊式向前星
struct NODE{
int to;
int nxt;
int c;
}node[MM];//鍊式向前星
int head[NM],lcnt=1;
void add(int a,int b,int c){
node[lcnt].to=b;
node[lcnt].c=c;
node[lcnt].nxt=head[a];
head[a]=lcnt++;
}
2.更新所有與根節點連接配接的最短路
for(int i=head[s];i;i=node[i].nxt){ //枚舉所有與起點連接配接的邊
int idx=node[i].to;
dis[idx]=min(node[i].c,dis[idx]); //更新最短路
}
dis[s]=0; //自身距離為0
book[s]=1; //标記搜尋過
使用book記錄是否作為過用來更新的點, 則搜完之後 book[s]=1
3.接下來枚舉除源點外所有點來作為用來更新最短路的點
依 ”從上次求出最短路的點中選出最短路最小的點“ 的順序周遊除源點以外的n-1個點
for(int kkk=1;kkk<n;kkk++){ //枚舉n-1次,因為原點已經被用來更新過了
int minn=INF,u=0;
for(int i=1;i<=n;i++){
if(!book[i]&&dis[i]<minn){ //枚舉每個已經被标記了但是沒有被搜尋過的點
u=i;
minn=dis[i]; //找距離最小的
}
}
. . .
4.從選出的點開始更新所有與它連接配接的邊
設已知 源點到i點的距離dis[i] 和 點i到點j的距離f[i][j] (未知目前dis [ j ]是否正确)
可以得到 dis [ j ] = min ( dis [ j ] , dis [ i ] + f [ i ] [ j ] )
根據上面的方程可以周遊所有與選出的點,算出最短路
. . .
for(int i=head[u];i;i=node[i].nxt){
int idx=node[i].to; //正在搜尋的點開始,枚舉每一條邊
dis[idx]=min(dis[idx],dis[u]+node[i].c); //更新最短距離,設f[i][j]為i到j的最大距離,d[i]為起始點到i的距離
//得到 d[j]=min(d[j],d[i]+f[i][j])
}
book[u]=1; //标記這個點搜尋過了
}
5.輸出
dis [ i ]就是源點到i點的距離
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
轉載于:https://www.cnblogs.com/dudujerry/p/9915505.html