个人比较喜欢,dijkstra和spfa
首先,存图方式有很多,个人喜欢链式前向星线性存图
flyod:
这个算法的复杂度是O(n^3),在竞赛中,一般超过一亿的算法就要谨慎,所以,这个可以在n<500的时候用。
1 注意判断重边。
2 注意赋值f[i][i]=0。
3 使用时注意条件。
4 if(dp[i][k]!=1e9&&dp[k][j]!=1e9)不加这一句的话会莫名其妙出错
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long u,v,w,n,m;
long long dp[1505][1505];
int main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j]=1e9;
}
}
for(int i=1;i<=n;i++) dp[i][i]=0;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&u,&v,&w);
dp[u][v]=min(dp[u][v],w);
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dp[i][k]!=1e9&&dp[k][j]!=1e9)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
}
}
}
if(dp[1][n]==1e9) printf("-1");
else printf("%lld",dp[1][n]);
return 0;
}
spfa:
不用判断重边
个人认为还是一样的思想,枚举中间节点
注意vis数组表示当前这个点有没有在队列内,如果不在,再进行最短路的查找
有缺点就是容易被卡,俗话说的好“spfa它已经死了”,(主要是因为时间复杂度过高),需要跑很多遍错误的前置答案
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int Maxn=2e3+5;
struct egde{
int to,next,val;
}e[50*Maxn];
queue<int> q;
int n,m,tot;
int head[Maxn],dis[Maxn];
bool vis[Maxn];
inline void add(int u,int v,int w)
{
e[++tot].to=v;
e[tot].next=head[u];
e[tot].val=w;
head[u]=tot;
}
inline void spfa(int st)
{
for(int i=1;i<=n;i++)
{
dis[i]=1e9;
}
dis[st]=0;vis[st]=1;
q.push(st);
while(!q.empty())
{
int now=q.front();
q.pop();vis[now]=0;
for(int i=head[now];i;i=e[i].next)
{
int nx=e[i].to;
if(dis[nx]>dis[now]+e[i].val)
{
dis[nx]=dis[now]+e[i].val;
if(vis[nx]==0)
{
vis[nx]=1;
q.push(nx);
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,u,v,w;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
spfa(1);
if(dis[n]==1e9) printf("-1");
else printf("%d",dis[n]);
return 0;
}
dijstra:
不用判断重边,但尤其注意不能有负边,一定注意。
时间复杂度低,主要用贪心的想法,可以用堆优化,还是用上为好
//xian-gaoxinyizhong-崔卓
//T3
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int Maxn=5e5;
struct egde{
int to,val,next;
}e[2*Maxn];
struct node{
int dis,num;
friend bool operator <(node x,node y)
{
return x.dis<y.dis;
}
}now;
priority_queue<node> q;
int n,m,tot;
int head[Maxn],dis[Maxn];
bool vis[Maxn];
inline void add(int u,int v,int w)
{
e[++tot].to=v;
e[tot].val=w;
e[tot].next=head[u];
head[u]=tot;
}
inline void dj()
{
for(int i=1;i<=n;i++)
{
dis[i]=1e9;
}
dis[1]=0;
now.dis=0;now.num=1;
q.push(now);
while(!q.empty())
{
now=q.top();q.pop();
if(vis[now.num]==0)
{
vis[now.num]=1;
for(int i=head[now.num];i;i=e[i].next)
{
if(dis[e[i].to]>dis[now.num]+e[i].val)
{
dis[e[i].to]=dis[now.num]+e[i].val;
if(vis[e[i].to]==0)
{
q.push((node){dis[e[i].to],e[i].to});
}
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,u,v,w;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dj();
if(dis[n]==-1e9)
{
printf("-1");
}
else printf("%d ",dis[n]);
return 0;
}
/*
7 7
1 2 1
2 5 1
2 3 1
3 6 1
3 4 1
4 7 1
2 7 1
*/
以上都要注意一个问题,开数组的时候,边和点的大小分开开,要不会炸