最短路问题
最短路问题我想分为3个环节来讲
1.Floyd
2.Dijkstra
3.SPFA
图论:点和边
最短路
多源最短路
一.定义:若干个点到其他点的最短路
当且仅当k在i到j的最短路上,取等
二.算法:
1.本质:
2.
3.初始化:若
for(int k=1;k<=n,k++) // 注意k要放在最外层的循环
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(r[i][j]>r[i][k]+r[j][k])
r[i][j]=r[j][i]=r[i][k]+r[j][k];
单源最短路
一.定义:一个点到其它点的最短路
二.算法
贪心求最短点,改用松弛求其他点,如此反复
朴素时间复杂度:
堆优化
// Dijkstra
void dijkstra(int n,int s){
for(int i=1;i<=n;i++){
int x;//x标记当前最短w的点
int min_dis=INF;//记录当前最小距离
for(int y=1;y<=n;y++){
if(!vis[y] && min_dis>=dis[y]){
x=y;
min_dis=dis[x];
}
}
vis[x]=true;
for(int y=1;y<=n;y++)
dis[y]=min(dis[y],dis[x]+G[x][y]);
}
}
// SPFA
int dis[N];
bool vis[N];
void SPFA(int S) {
memset(vis, false, sizeof(vis));
memset(dis, INF, sizeof(dis));
dis[S] = 0;
queue<int> Q;
Q.push(S);
while (!Q.empty()) {
int x = Q.front();
Q.pop();
vis[x] = false;
for (int i = head[x]; i != -1; i = edge[i].next) {
int to = edge[i].to;
if (dis[to] > dis[x] + edge[i].dis) {
dis[to] = dis[x] + edge[i].dis;
if (!vis[to]) {
vis[to] = true;
Q.push(to);
}
}
}
}
}
总结
1.判断多源还是单源最短路
2.如果是单源最短路,看看边权是不是为负,非负可以用
Dijkstra(不能处理负边权,具体见link)
#include<bits/stdc++.h>
#define int long long
const int N = 2e6 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
inline int read()
{
int s = 0 ;
char ch = getchar();
bool f = true;
while(ch < '0' || ch > '9')
{
if(ch == '-') f = false;
ch = getchar();
}
while(ch >='0' && ch<='9')
{
s = s * 10 + ch - '0';
ch = getchar();
}
return f ? s : ~s + 1;
}
int n,m,s,f[N],vis[N];
struct nod{
int no,w;
bool operator < (const nod &x) const {
return x.w < w;
}
};
priority_queue<nod>q;
struct node{
int v,w,next;
}edge[N];int cnt,head[N];
inline void add(int u,int v,int w)
{
cnt++;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
inline void Dijkstra()
{
for(int i=1;i<=n;i++) f[i] = INF;f[s] = 0;
q.push(nod{s,0});
while(!q.empty())
{
int now = q.top().no;q.pop();
if(vis[now]) continue;vis[now] = 1;
for(int i=head[now];i;i=edge[i].next)
{
int v = edge[i].v , w = edge[i].w;
if(f[v] > f[now] + w)
{
f[v] = f[now] + w;
if(!vis[v]) q.push(nod{v,f[v]});
}
}
}
}
signed main()
{
n = read();m = read();s = read();
for(int i=1;i<=m;i++)
{
int u = read() , v = read() , w = read();
add(u,v,w);
}
// spfa(); TLE
Dijkstra();
for(int i=1;i<=n;i++) cout << f[i] << " ";
return 0;
}
spfa(TLE大法)
#include<bits/stdc++.h>
#define int long long
const int N = 2e6 + 5;
const int INF = 2147483647;
using namespace std;
inline int read()
{
int s = 0 ;
char ch = getchar();
bool f = true;
while(ch < '0' || ch > '9')
{
if(ch == '-') f = false;
ch = getchar();
}
while(ch >='0' && ch<='9')
{
s = s * 10 + ch - '0';
ch = getchar();
}
return f ? s : ~s + 1;
}
int n,m,s,f[N],vis[N];
queue<int>q;
struct node{
int v,w,next;
}edge[N];int cnt,head[N];
inline void add(int u,int v,int w)
{
cnt++;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
inline void spfa()
{
for(int i=1;i<=n;i++) f[i] = INF;f[s] = 0 ;
q.push(s);
while(!q.empty())
{
int now = q.front();q.pop();
vis[now] = 0;
for(int i=head[now];i;i=edge[i].next)
{
int v = edge[i].v , w = edge[i].w;
if(f[v] > f[now] + w)
{
f[v] = f[now] + w;
if(!vis[v]) q.push(v) , vis[v] = 1;
}
}
}
}
signed main()
{
n = read();m = read();s = read();
for(int i=1;i<=m;i++)
{
int u = read() , v = read() , w = read();
add(u,v,w);
}
spfa();
for(int i=1;i<=n;i++)
{
if(s == i)
{
cout << 0 << " ";
continue;
}
if(f[i]) cout << f[i] << " ";
else cout << INF << " ";
}
return 0;
}
__EOF__
凡是过往,皆为序章,前途似海,来日方长
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee