1. Floyd
时间复杂度:
优势:简单,代码量小,处理多源最短路
劣势:效率低
注意:中间节点在最外层枚举(等价于向原图添加节点扩大问题规模)
//hdu 2544
#include
#include
#include
#include
using namespace std;
const int N=104;
const int INF=0x3f3f3f3f;
int f[N][N];
int n,m;
int main() {
while (scanf("%d%d",&n,&m)&&(n||m)) {
memset(f,INF,sizeof(f));
for (int i=1;i<=n;++i)
f[i][i]=0;
while (m--) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
f[u][v]=w,f[v][u]=w;
}
for (int k=1;k<=n;++k)
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
printf("%d\n",f[1][n]);
}
return 0;
}
2. Dijkstra
时间复杂度:
优势:简单,代码量小,处理单源最短路
劣势:效率较低,无法处理含有负边权的图
注意:中间节点在最外层枚举(等价于向原图添加节点扩大问题规模)
//hdu 2544
#include
#include
#include
#include
using namespace std;
const int N=104;
const int M=1e4+4;
const int INF=0x3f3f3f3f;
int n,m;
struct Edge {
int v,w,nxt;
}e[M<<1];
int head[N],etot;
int dis[N];
bool vis[N];
inline void adde(int u,int v,int w) {
e[++etot].nxt=head[u],e[etot].v=v,e[etot].w=w,head[u]=etot;
}
inline void init() {
memset(vis,false,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(head,-1,sizeof(head));
etot=0,dis[1]=0;
}
int main() {
while (scanf("%d%d",&n,&m)&&(n||m)) {
init();
while (m--) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);
adde(v,u,w);
}
for (int t=1;tdis[i]&&!vis[i]) {
p=i;
d=dis[i];
}
}
vis[p]=true;
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
dis[v]=min(dis[v],d+e[i].w);
}
}
printf("%d\n",dis[n]);
}
return 0;
}
3. Dijkstra + Heap
时间复杂度:
优势:效率较高,处理单源最短路
劣势:无法处理含有负边权的图
注意:加入遍历标记防止重复遍历同一个点进行无效松弛操作,可能被较强数据卡掉
//Luogu 4479
#include
#include
#include
#include
#include
using namespace std;
const int N=1e5+4;
const int M=2e5+4;
const int INF=0x3f3f3f3f;
int n,m,dis[N],s;
bool vis[N];
struct Edge {
int v,nxt,w;
}e[M<<1];
int head[N],etot;
struct Node {
int id,dis;
friend bool operator <(const Node &a,const Node &b) {
return a.dis>b.dis;
}
};
inline int read() {
int x=0;char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
inline void adde(int u,int v,int w) {
e[++etot].nxt=head[u],e[etot].v=v,e[etot].w=w,head[u]=etot;
}
inline void dijkstra(int S) {
priority_queue q;
memset(dis,INF,sizeof(dis));
dis[S]=0;
q.push((Node){S,0});
while (!q.empty()) {
Node cur=q.top();
q.pop();
int p=cur.id;
if (vis[p]) continue;
vis[p]=true;
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
if (dis[v]>dis[p]+e[i].w) {
dis[v]=dis[p]+e[i].w;
q.push((Node){v,dis[v]});
}
}
}
}
int main() {
memset(head,-1,sizeof(head));
n=read(),m=read(),s=read();
for (register int i=0;i
4. SPFA
时间复杂度:,k一般不大于2,最坏为
优势:可处理含负边权的图,可用于判负环
劣势:效率较高但可能被卡
注意:入队标记!!!
//Luogu 3371
#include
#include
#include
#include
#include
using namespace std;
const int N=1e4+4;
const int M=5e5+4;
const int INF=0x3f3f3f3f;
int n,m,dis[N],s;
bool vis[N];
struct Edge {
int v,nxt,w;
}e[M<<1];
int head[N],etot;
inline int read() {
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
inline void adde(int u,int v,int w) {
e[++etot].nxt=head[u],e[etot].v=v,e[etot].w=w,head[u]=etot;
}
inline void SPFA(int S) {
queue q;
memset(dis,INF,sizeof(dis));
dis[S]=0,vis[S]=true;
q.push(S);
while (!q.empty()) {
int p=q.front();
q.pop();
vis[p]=false;
for (int i=head[p];~i;i=e[i].nxt) {
int v=e[i].v;
if (dis[v]>dis[p]+e[i].w) {
dis[v]=dis[p]+e[i].w;
if (!vis[v]) {
vis[v]=true;
q.push(v);
}
}
}
}
}
int main() {
memset(head,-1,sizeof(head));
n=read(),m=read(),s=read();
for (register int i=0;i