Spfa
Spfa是类似bfs的一种图论方法,运用队列更新dis[i],求得图中1~n的最短路径。
Spfa中用到dis[i]表示图中每一点距离起点的长度,bz[i]用来记录编号为i的点是否入队,a[x,y]表示图中x~y之间的距离,b[x,i]表示编号为x的点的第i条边的终点,每次更新这个终点到起点的距离,以当前入队的点来更新,最后求出答案。
tov[i]表示编号为i的边的终点;
next[i]表示编号为i的边下一个要搜索的边;
last[i]表示以i为节点开始的最后一条边;
len[i]表示编号为i的权值;
##Code
#include<cstdio>
#include<cmath>;
#include<iostream>
using namespace std;
int n,m,i,next[100001],len[100001],last[10001],tov[100001],tot,head,tail,dis[10001],f[10000001];
bool bz[10001];
void insert(int x,int y,int z)
{
tot++;
len[tot]=z;
tov[tot]=y;
next[tot]=last[x];
last[x]=tot;
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
}
head=0;
tail=1;
for (i=1;i<=n;i++)
dis[i]=2147483647/2;
dis[1]=0;
bz[1]=true;
f[1]=1;
while (head!=tail)
{
head++;
x=f[head];
i=last[x];
while (i!=0)
{
y=tov[i];
if (dis[x]+len[i]<dis[y])
{
dis[y]=dis[x]+len[i];
if (bz[y]==false)
{
bz[y]=true;
tail++;
f[tail]=y;
}
}
i=next[i];
}
bz[x]=false;
}
for (i=2;i<=n;i++)
{
if (dis[i]!=2147483647/2)
printf("%d\n",dis[i]);
else printf("%d\n",-1);
}
}
Dijkstra
Dijkstra是一种以贪心为主导思想的单源最短路径算法。
每次找到所有dis值最小的那一个用它来更新其他点。从而实现单源最短路径。
Code
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,next[100001],len[100001],last[10001],tov[100001],tot,head,tail,dis[10001],f[10000001];
bool bz[10001];
void insert(int x,int y,int z)
{
len[++tot]=z;
tov[tot]=y;
next[tot]=last[x];
last[x]=tot;
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z,i,j,k,p;
memset(dis,127,sizeof(dis));
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
if(x==1) dis[y]=min(dis[y],z);
}
dis[1]=0;
bz[1]=true;
for (i=1;i<=n;++i)
{
p=2147483647;
for (j=1;j<=n;++j)
{
if(!bz[j]&&dis[j]<p)
{
p=dis[j];
k=j;
}
}
bz[k]=true;
for (j=last[k];j;j=next[j])
dis[tov[j]]=min(dis[k]+len[j],dis[tov[j]]);
}
for (i=2;i<=n;i++)
{
if (dis[i]<2147483647/2)
printf("%d\n",dis[i]);
else printf("%d\n",-1);
}
}
加堆优化:
Dijkstra加堆优化最大的要点就是要记录每个点在堆中的位置,并且在每次更新完之后要把那个点在堆中up一下,不然堆的形态对于更新完之后的dis值来说就是错误的。
Code
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=5e6+10;
int n,m,tot,s;
int dis[maxn];
int las[maxn],nex[maxn*2],tov[maxn*2],len[maxn*2];
int d[maxn],id[maxn];
void ins(int x,int y,int z){
tov[++tot]=y,nex[tot]=las[x],las[x]=tot,len[tot]=z;
tov[++tot]=x,nex[tot]=las[y],las[y]=tot,len[tot]=z;
}
void up(int x){
while(x>1&&dis[d[x]]<dis[d[x/2]]){
swap(d[x],d[x/2]);
swap(id[d[x]],id[d[x/2]]);
x>>=1;
}
}
void down(int x){
while(x*2<=d[0]&&dis[d[x]]>dis[d[x*2]]||x*2+1<=d[0]&&dis[d[x]]>dis[d[x*2+1]]){
int k=x*2;
if(k<d[0]&&dis[d[k+1]]<dis[d[k]]) ++k;
swap(d[x],d[k]);
swap(id[d[x]],id[d[k]]);
x=k;
}
}
int main(){
scanf("%d%d%d",&n,&m,&s);
int i,j,x,y,z;
for (i=1;i<=m;++i) scanf("%d%d%d",&x,&y,&z),ins(x,y,z);
memset(dis,127,sizeof(dis));
dis[1]=0;
for (i=1;i<=n;++i) d[++d[0]]=i,id[i]=d[0],up(d[0]);
for (i=1;i<=n;++i){
int p=d[1];
d[1]=d[d[0]--];
id[d[1]]=1;
down(1);
for (j=las[p];j;j=nex[j]){
dis[tov[j]]=min(dis[tov[j]],dis[p]+len[j]);
up(id[tov[j]]);
}
}
printf("%d\n",dis[s]);
}
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1e3 + 10;
const int maxm = 1e4 + 10;
int n, m, c, tot;
int dis[maxn];
int vis[maxn];
int las[maxn], nex[2 * maxm], tov[2 * maxm];
struct node
{
int id;
bool operator<(const node &a) const
{
return dis[id] < dis[a.id];
}
bool operator>(const node &a) const
{
return dis[id] > dis[a.id];
}
} poi[maxn];
void add(int x, int y)
{
tov[++tot] = y;
nex[tot] = las[x];
las[x] = tot;
}
void spfa(int st)
{
queue<int> Q;
dis[c] = 0;
vis[c] = 1;
Q.push(st);
while (!Q.empty())
{
int x = Q.front();
for (int i = las[x]; i; i = nex[i])
{
int y = tov[i];
if (dis[y] > dis[x] + 1)
{
dis[y] = dis[x] + 1;
if (!vis[y])
{
vis[y] = 1;
Q.push(y);
}
}
}
Q.pop();
vis[x] = 0;
}
}
void dijstra(int st)
{
dis[st] = 0;
priority_queue<node, vector<node>, greater<node>> P;
P.push((node){st});
while (!P.empty())
{
node x = P.top();
P.pop();
if (vis[x.id])
continue;
vis[x.id] = 1;
for (int i = las[x.id]; i; i = nex[i])
{
int y = tov[i];
if (dis[y] > dis[x.id] + 1)
{
dis[y] = dis[x.id] + 1;
P.push((node){y});
}
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &c);
int i, j, x, y;
for (i = 1; i <= m; ++i)
{
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
// for (i = 1; i <= n; ++i)
// dis[i] = 1e9, vis[i] = 0;
// spfa(c);
for (i = 1; i <= n; ++i)
{
dis[i] = 1e9;
poi[i].id = i;
}
dijstra(c);
for (i = 1; i <= n; ++i)
printf("%d\n", dis[i]);
}