//dijkstra算法求單源點最短路:相似求最小生成樹的prim算法。要求邊權值非負。 #include<iostream> #include<cstring> using namespace std; const int MAX=10000007; int mp[1005][1005],dis[1005],vis[1005]; int n,m; void dijk(int s)//求s到每一個點的最短路 { for(int i=1;i<=n;i++) //初始化s到每一個點的距離 { dis[i]=mp[s][i]; vis[i]=0; } vis[s]=1; for(int i=1;i<=n;i++)//n次循環 { int Min=MAX,sta=0; for(int j=1;j<=n;j++) { if(!vis[j]&&dis[j]<Min) { Min=dis[j]; sta=j; } } if(sta==0) continue; vis[sta]=1; for(int j=1;j<=n;j++)//鬆弛 { if(!vis[j]&&mp[sta][j]!=MAX&&dis[j]>dis[sta]+mp[sta][j]) dis[j]=dis[sta]+mp[sta][j]; } } } int main() { return 0; } ************************************************************************** //floyd算法求每兩個點之間的最短路。三重循環。要求邊權值非負 for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(mp[i][j]>mp[i][k]+mp[k][j]){ mp[i][j]=mp[i][k]+mp[k][j]; } } } } *************************************************************************** //spfa算法適用於邊權值爲正和負的兩種狀況。victor寫的。容易爆內存。 /* 1.隊列Q={s} 2.取出隊頭u,枚舉全部的u的臨邊 .若d(v)>d(u)+w(u,v)則改進 ,pre(v)=u,因爲d(v) 減小了,v可能在之後改進其餘的點,因此若v不在Q中,則將v入隊。 3.一直迭代2,直到隊列Q爲空(正常結束),或有的點的入隊次數>=n(含有負圈)(加一個cnt數組 記錄每一個點的入隊次數)。 */ #include<iostream> #include<cstring> #include<queue> #include<vector> using namespace std; const int inf=9999999; int vis[10004],dis[10004],n; struct node{ int from,to,value; }; vector<node>g[10004]; void spfa(int s) { for(int i=0;i<=n;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); vis[s]=1; dis[s]=0; queue<int>q; q.push(s); while(!q.empty()){ int cur=q.front(); q.pop(); for(int i=0;i<(int)g[cur].size();i++){ int k=g[cur][i].to; if(dis[k]>dis[cur]+g[cur][i].value){ dis[k]=dis[cur]+g[cur][i].value; if(!vis[k]){ vis[k]=1; q.push(k); } } } vis[cur]=0; } } int main() { return 0; } /***************************************************************/ //spfa 模板和上一個相比佔用內存小 #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn=50004,inf=0x7fffffff; struct node { int to,next,val; } edge[maxn*4];//! int mark[maxn],head[maxn],tot,dis[maxn],n,m; void add(int a,int b,int c) { edge[tot].to=b; edge[tot].next=head[a]; edge[tot].val=c; head[a]=tot++; } void spfa(int s) { for(int i=0;i<=n;i++) dis[i]=inf; memset(mark,0,sizeof(mark)); queue<int>q; dis[s]=0; mark[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); mark[u]=0; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].to; if(dis[v]>dis[u]+edge[i].val) { dis[v]=dis[u]+edge[i].val; if(!mark[v]) { q.push(v); mark[v]=1; } } } } } main() { while(scanf("%d%d",&n,&m)==2){ int a,b,c; memset(head,-1,sizeof(head));//記住初始化head和tot tot=0; //邊的編號從0開始 for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); //add(b,a,c);反向邊 } spfa(0); printf("%d\n",dis[n-1]); } return 0; }