个人比较喜欢,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 */
以上都要注意一个问题,开数组的时候,边和点的大小分开开,要不会炸