P3371 【模板】单源最短路径(弱化版)
P4779 【模板】单源最短路径(标准版)
Floyd 算法 - 邻接矩阵 (70分)
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
const int INF=(1<<30);
using namespace std;
const int maxn=1e4+7;
int n,m,s;//点、边、出发点
int f[maxn][maxn];
void floyd(){
FOR(k,1,n){
FOR(i,1,n){
if(i==k or f[i][k]==INF) continue;
FOR(j,1,n){
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
}
}
f[s][s]=0;
}
int main(){
cin>>n>>m>>s;
FOR(i,1,n)
FOR(j,1,n)
f[i][j]=INF;
int u,v,w;
FOR(i,1,m){
cin>>u>>v>>w;
f[u][v]=min(f[u][v],w);//去重边
}
floyd();
FOR(i,1,n){
if(f[s][i]!=INF) cout<<f[s][i]<<" ";
else cout<<INT_MAX<<" ";
}
return 0;
}
Bellman-Ford 算法 - 直接存边 (70分)
参考代码对于源点的距离赋值顺序有误
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
const int maxn=1e4+7;
const int maxm=5e5+7;
const int INF=(1<<30);
struct Edge{
int u,v,w;
};
Edge edge[maxm];
int dist[maxn];//结点到源点最小距离
int n,m,s;//结点数,边数,源点
// 初始化图
void init(){
FOR(i,1,n)
dist[i]=INF;
FOR(i,1,m){
int u,v,w;
cin>>u>>v>>w;
edge[i]={u,v,w};
if(u==s) dist[v]=w;
}
dist[s]=0;
}
void relax(int u,int v,int w){
if(dist[v]>dist[u]+w) dist[v]=dist[u]+w;
}
bool Bellman_Ford(){
FOR(i,1,n-1)
FOR(j,1,m)
relax(edge[j].u,edge[j].v,edge[j].w);
bool flag=true;
FOR(i,1,m)//判断是否有负环路
if(dist[edge[i].v]>dist[edge[i].u]+edge[i].w){
flag=false;
break;
}
return flag;
}
int main(){
cin>>n>>m>>s;
init();
if(Bellman_Ford()){
FOR(i,1,n){
if(dist[i]!=INF) cout<<dist[i]<<" ";
else cout<<INT_MAX<<" ";
}
}
return 0;
}
SPFA 算法 - 链式前向星 (100分)
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
const int maxn=1e4+7;
const int maxm=5e5+7;
const int INF=(1<<30);
int n,m,s,adt=0;
int dis[maxn],vst[maxn],head[maxm];
struct Edge{
int to,nxt,w;
}e[maxm];
void add(int u,int v,int w){
e[++adt]={v,head[u],w};
head[u]=adt;
}
void SPFA(){
queue<int> q;
FOR(i,1,n){
dis[i]=INF;
vst[i]=0;//记录点i是否在队列中
}
dis[s]=0;
q.push(s);
vst[s]=1;//第一个顶点入队,进行标记
while(!q.empty()){
int u=q.front();//取出队首
q.pop();
vst[u]=0;//出队标记
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vst[v]){
vst[v]=1;//标记入队
q.push(v);
}
}
}
}
dis[s]=0;
}
int main(){
cin>>n>>m>>s;
FOR(i,1,m){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
SPFA();
FOR(i,1,n){
if(dis[i]!=INF) cout<<dis[i]<<" ";
else cout<<INT_MAX<<" ";
}
return 0;
}
Dijkstra 算法 - 链式前向星 (100分)
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
const int maxn=1e4+7;
const int maxm=5e5+7;
const int INF=(1<<30);
int n,m,s;
int dis[maxn],vst[maxn];
int head[maxm],adt;
struct Edge{
int to,nxt,w;
}e[maxm];
void add(int u,int v,int w){
e[++adt]={v,head[u],w};
head[u]=adt;
}
void dijkstra(){
int u=s;
while(!vst[u]){
int min0=INF;
vst[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(!vst[v]) dis[v]=min(dis[v],dis[u]+w);
}
FOR(i,1,n)
if(!vst[i] and dis[i]<min0) min0=dis[i],u=i;
}
}
int main(){
cin>>n>>m>>s;
FOR(i,1,n)
dis[i]=INF;
dis[s]=0;
FOR(i,1,m){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
dijkstra();
FOR(i,1,n){
if(dis[i]!=INF) cout<<dis[i]<<" ";
else cout<<INT_MAX<<" ";
}
return 0;
}
Dijkstra 算法 - 链式前向星 & 优先队列 (100分)
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
const int maxn=1e5+7;//弱化版是1e4
const int maxm=2e5+7;//弱化版是4e5
const int INF=(1<<30);
int n,m,s;
int dis[maxn],vst[maxn];
int head[maxm],adt;
struct Edge{
int to,nxt,w;
}e[maxm];
void add(int u,int v,int w){
e[++adt]={v,head[u],w};
head[u]=adt;
}
struct node{
int dis,u;
bool operator <(const node &x)const{
return x.dis<dis;
}
};
void dijkstra(){
priority_queue<node> q;
q.push({0,s});
dis[s]=0;
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vst[u]) continue;
vst[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vst[v]) q.push({dis[v],v});
}
}
}
}
int main(){
cin>>n>>m>>s;
FOR(i,1,n)
dis[i]=INF;
dis[s]=0;
FOR(i,1,m){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
dijkstra();
FOR(i,1,n){
if(dis[i]!=INF) cout<<dis[i]<<" ";
else cout<<INT_MAX<<" ";
}
return 0;
}