#https://vjudge.net/problem/HDU-2544
题意概括
寻找单源最短路径。
代码(多个)
在学习Bellmann-Ford算法及其变形SPFA,感觉挺有意思,就都写了一遍,以供学习。
淳朴的Bellmann-Ford
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int inf=1e9;
struct node
{
int u,v,w;
}edge[2*maxn];
int n,m,dis[maxn];
void Bellman()
{
int i,k;
dis[1]=0;
for(i=2;i<=n;i++)
{
dis[i]=inf;
}
for(k=1;k<=n-1;k++)
{
int flag=0;
for(i=1;i<=2*m;i++)///双向边,所以是2*m
{
if(dis[edge[i].v]>dis[edge[i].u]+edge[i].w)
{
flag=1;///记录本次有没有松弛
dis[edge[i].v]=dis[edge[i].u]+edge[i].w;
}
}
if(!flag) break;
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
int i,cnt=1;
for(i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[cnt].u=a,edge[cnt].v=b,edge[cnt].w=c,cnt++;///注意是双向边!!!
edge[cnt].u=b,edge[cnt].v=a,edge[cnt].w=c,cnt++;
}
Bellman();
printf("%d\n",dis[n]);
}
return 0;
}
SPFA+vector存图
#include <bits/stdc++.h>
using namespace std;
const int maxn=105;
const int inf=1e9;
struct edge
{
int u,v,w;
edge(int a,int b,int c):u(a),v(b),w(c){}
};
int n,m,dis[maxn],vis[maxn];
vector<edge>e[maxn];
void SPFA(int s)
{
queue<int>q;
q.push(s);
int i;
dis[s]=0,vis[s]=1;
for(i=2;i<=n;i++)
{
dis[i]=inf;
}
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(i=0;i<e[u].size();i++)
{
int v=e[u][i].v,w=e[u][i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
int i;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++) e[i].clear();///注意每次清空
for(i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e[a].push_back(edge(a,b,c));
e[b].push_back(edge(b,a,c));
}
SPFA(1);
printf("%d\n",dis[n]);
}
return 0;
}
SPFA+链式前向星+判断负环+打印路径
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;///由于是链式前向星,所以edge的边数上限是maxn
const int inf=1e8;
struct edge
{
int to,next,w;
}edge[maxn];
int n,m,cnt,dis[maxn],vis[maxn],head[maxn],neg[maxn],pre[maxn];
void init()
{
for(int i=1;i<=n;i++)///数组越界警告!!(所以maxn设大一点很有必要)
{
head[i]=-1;
edge[i].to=-1;
}
cnt=0;
}
void addedge(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void print_path(int s,int t)///从s到t的路径输出
{
if(s==t)
{
printf("%d ",s);
return;
}
print_path(s,pre[t]);
printf("%d ",t);
}
int SPFA(int s)
{
queue<int>q;
q.push(s);
int i;
dis[s]=0,vis[s]=1,neg[s]=1;
for(i=2;i<=n;i++)
{
dis[i]=inf;
}
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(i=head[u];~i;i=edge[i].next)
{
int v=edge[i].to,w=edge[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
if(!vis[v])
{
vis[v]=1;
neg[v]++;
q.push(v);
if(neg[v]>n) return 0;///出现负圈
}
}
}
}
return 1;
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
int i;
memset(vis,0,sizeof(vis));
memset(neg,0,sizeof(neg));
init();
for(i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
SPFA(1);
printf("%d\n",dis[n]);
}
return 0;
}