用spfa做,额,到目前为止做的题目都几乎是模板题,三四道都是改一下输入就了事了,不过针对题目而已,还真有选择的余地,这里一个是我的,额,内存开得太大了,主要是1000*1000的矩阵来保存一个图的信息,本来很明显的得用邻接表来储存的,,而且只保存有用的边,而且加上用队列优化,快了不少呢
对比一下俩个代码吧
用邻接表的:
#include<cstdio>
#include<iostream>
using namespace std;
#define N 4000
struct edge{
int v,next,cost;
edge(int _v=0 ,int _next=0,int _cost=0):v(_v),next(_next),cost(_cost){};
}e[N];
int dist[N];
int n,m,p[N],tot = 0;
void spfa(int s)
{
bool vist[N];
memset(vist,false ,sizeof(vist));
memset(dist,1,sizeof(dist));
dist[s] = 0;
int que[N];
int begin,end;
begin = end = 0;
que[end++] = s;
vist[s] = true;
while(begin<end)
{
int t = que[begin++];
vist[t] = false;
for(int j = p[t];j!=-1;j = e[j].next)
{
if(dist[e[j].v]>e[j].cost+dist[t])
{
dist[e[j].v] = e[j].cost+dist[t];
if(!vist[e[j].v])
{
vist[e[j].v] = true;
que[end++] = e[j].v;
}
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
tot = 0;
memset(p,-1,sizeof(p));
int a,b,c;
for(int i = 0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
e[tot]=edge(b,p[a],c);
p[a] = tot++;
e[tot]=edge(a,p[b],c);
p[b] = tot++;
}
spfa(1);
printf("%d\n",dist[m]);
}
}
直接用邻接矩阵保存的:
#include<iostream>
#define MAXINT 999999
using namespace std;
int m,n;
int dis[1001],Q[10010],vis[1001];
int map[1001][1001];
void SPFA(int n, int s)
{
// pri是队列头结点,end是队列尾结点
int i, pri, end, p;
memset(vis, 0, sizeof(vis));
for(int i=0; i<10010; ++i)
Q[i] = 0;
for (i=1; i<=n; i++)
dis[i] =MAXINT;
dis[s] = 0;
vis[s] = 1;
Q[1] = s; pri = 1; end = 2;
while (pri < end)
{
p = Q[pri];
for (i=1; i<=n; ++i)
{
//更新dis
if (dis[p]+map[p][i] < dis[i])
{
dis[i] = dis[p]+map[p][i];
if (!vis[i]) //未在队列中
{
Q[end++] = i;
vis[i] = 1;
}
}
}
vis[p] = 0; // 置出队的点为未标记
pri++;
}
}
int main()
{
while(cin>>m>>n)
{
int a,b,len;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
map[i][j]=MAXINT;
for(int i=1;i<=m;i++)
{
cin>>a>>b>>len;
if(map[a][b]>len)
{
map[a][b]=len;
map[b][a]=len;
}
}
SPFA(n,1);
cout<<dis[n]<<endl;
}
return 0;
}