您的位置:首页 > 其它

[HDU 2544] 最短路 spfa写法 + 链式前向星

2016-05-11 10:43 489 查看
spfa是对迪杰斯特拉算法的队列优化,套路大概就是:

让dis[1] 入队, 然后判断队列是否为空;

让它赋给队首, 然后就是一样的循环;

唯一的区别就是这个地方!vis[i] 是拆开放在后面的;

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
#define inf 9999999
using namespace std ;
int dis[2000] , vis[2000] , map[200][2000] , u , v ;
void input();
void init();
void spfa();
void output();

int main()
{
while(scanf("%d%d",&v,&u),v+u)
{
init();
input();
spfa();
output();
}
}

void input()
{
for(int i = 0 ; i < u;i++)
{
int a , b , len ;
scanf("%d%d%d",&a,&b,&len);
if(map[a][b] > len)
{
map[a][b] = map[b][a] = len ;
}
}
}

void init()
{
for(int i = 0 ; i <=v ;i++)
{
for(int j = 0 ; j<=v;j++)
{
map[i][j] = inf ;
}
dis[i] = inf ;
vis[i] = 0 ;
map[i][i] = 0 ;
}
}

void output()
{
printf("%d\n",dis[v]);
}

void spfa()
{
queue<int>Q;
dis[1] = 0 ;
Q.push(1);
vis[1] = 1 ;//*初始点肯定是会被使用了的
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = 0 ;  //*这个地方是0不是1 ; 因为出队时候这个now还并没有被使用
for(int i = 1 ; i <=v ;i++)
{
if(dis[i] > dis[now] + map[now][i])
{
dis[i] = dis[now] + map[now][i];
if(!vis[i])
{
Q.push(i);
vis[i] = 1 ;//*使用了后就标记
}
}
}
}
}


链式前向星写法:

#include <bits/stdc++.h>
#define inf 9999999
using namespace std ;
int head[11000] , vis[110] , dis[110] ;
struct node {
int to ;//*表示第i边的终点
int next;//*表示与i边同起点的下一条边的位置
int val;//*当前边的权值
}edge[11000];
int u , v , ans ;//*u是边,v是点,ans是队位置
void add(int u , int v , int val)
{
int i , t = 0 ;
for(i = head[u] ; i!=-1 ; i = edge[i].next)  //*去重
{
if(v ==edge[i].to && val >= edge[i].val)
{
t = 1 ;
break;
}
}
if(t==1) return ;
edge[ans].to = v ;//*构建无向图
edge[ans].val = val;
edge[ans].next = head[u] ;
head[u] = ans++;
edge[ans].to = u ;
edge[ans].val = val;
edge[ans].next = head[v];
head[v] = ans++;
return ;
}

void spfa()
{
queue<int>Q;
dis[1] = 0 ;
vis[1] = 1 ;
Q.push(1);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = 0 ;
for(int i = head[now] ; i!=-1 ;i = edge[i].next)  //*遍历同起点的所有边
{
int v = edge[i].to ;
if(dis[v] > dis[now] + edge[i].val)
{
dis[v] = dis[now] + edge[i].val;
if(!vis[v])
{
Q.push(v);
vis[v] = 1 ;
}
}
}
}

}
int main()
{
while(scanf("%d%d",&v,&u)!=EOF)
{
if(u==0&&v==0) break;
ans = 0 ;
for(int i = 0 ; i<=v;i++)
{
dis[i] = inf ;
vis[i] = 0 ;
}
memset(head,-1,sizeof(head));
for(int i = 0 ; i < u ; i++)
{
int a , b , len ;
scanf("%d%d%d",&a,&b,&len);
add(a,b,len);
}
spfa();
cout<<dis[v]<<endl;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: