一:单源最短路径
1.Dijkstra:从源点开始,然后开始扩展节点,更新边
因为用了优先级队列来优化找最小值的过程,时间复杂度为O(elogv)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 105
#define MAX 0x3f3f3f3f
struct edge
{
int to,next,v;
};
struct node
{
int to,v;
bool operator <(const node &t)const{
return v>t.v;
}
};
edge e[maxn*maxn];
int head[maxn];
int dis[maxn];
int vis[maxn];
priority_queue<node> q;
void add(int h,int a,int b,int c)
{
e[h].to=b,e[h].next=head[a];
e[h].v=c,head[a]=h;
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF&&m+n)
{
memset(head,-1,sizeof(head));
memset(e,0,sizeof(e));
int h=0;
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(h,a,b,c);
h++;
add(h,b,a,c);
h++;
}
memset(dis,MAX,sizeof(dis));
memset(vis,0,sizeof(vis));
while(!q.empty())
q.pop();
dis[1]=0;
vis[1]=1;
q.push(node{1,0});
while(!q.empty())
{
node t=q.top();
q.pop();
if(vis[t.to])
continue;
vis[t.to]=1;
for(int i=head[t.to];i>-1;i=e[i].next)
{
edge g=e[i];
if(dis[g.to]>g.v+t.v)
{
dis[g.to]=g.v+t.v;
q.push(node{g.to,dis[g.to]});
}
}
}
printf("%d\n",dis[n]);
}
return 0;
}
2.Bellman-Ford (对每条边进行松弛,可以判负环)
时间复杂度为 O(v*e)(节点数*总边数)
参考:http://www.cnblogs.com/tanky_woo/archive/2011/01/17/1937728.html
模板
bool Bellman_Ford()
{
memset(dis,MAX,sizeof(dis));
dis[original]=0;
for(int i = 1; i <= nodenum - 1; ++i) //边数
for(int j = 1; j <= edgenum; ++j) //对每一条边进行松弛
if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛
{
dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
pre[edge[j].v] = edge[j].u;
}
bool flag = 1; //判断是否含有负权回路
for(int i = 1; i <= edgenum; ++i) //如果还能松弛的话,则说明有负环
if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)
{
flag = 0;
break;
}
return flag;
}
二:任意两点间的最短路问题
Floyd-Warshall
也可以处理边是负数的问题,判断负环,只用判断d[i][i]是不是负数
void warshall_floyd()
{
for(int k=0;k<v;k++)
{
for(int i=0;i<v;i++)
{
for(int j=0;j<v;j++)
{
d[i][j]=min(d[i][j],d[i])
}
}
}
}
路径还原,只用加一个数组里面放前驱。