优化后的SFPA和Dijkstra:
SPFA模板:
```
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
struct edge{
int to,nxt,w;
edge(int t=0,int n=0,int w=0):to(t),nxt(n),w(w){}
}E[N*5];
int tot,head[N*5];
int vis[N],d[N];
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w)
{
E[tot] = edge(v,head[u],w);
head[u] = tot++;
}
void SPFA(int s)
{
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
queue<int> q;
q.push(s);
vis[s] = 1;
d[s] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
vis[u] = 0;
for(int i = head[u];~i;i = E[i].nxt)
{
int v = E[i].to,w = E[i].w;
if(d[v] > d[u] + w)
{
d[v] = d[u] + w;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main()
{
int n,m,u,v,w;
while(~scanf("%d%d",&n,&m) && (n || m))
{
init();
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
SPFA(1);
printf("%d\n",d[n]);
}
return 0;
}
```
Dijkstra:
```
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
struct edge{
int to,nxt,w;
edge(int t=0,int n=0,int w=0):to(t),nxt(n),w(w){}
}E[N*5];
int tot,head[N*5];
int vis[N],d[N];
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w)
{
E[tot] = edge(v,head[u],w);
head[u] = tot++;
}
struct node{
int v,w;
node(int v=0,int w=0):v(v),w(w){}
bool operator < (const node & p)const{
return w > p.w;
}
};
void Dijkstra(int s)
{
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
priority_queue<node> q;
d[s] = 0;
q.push(node(s,d[s]));
while(!q.empty())
{
int u = q.top().v;q.pop();
if(vis[u])
continue;
vis[u] = 1;
for(int i = head[u];~i;i = E[i].nxt)
{
int v = E[i].to,w = E[i].w;
if(!vis[v] && d[v] > d[u] + w)
{
d[v] = d[u] + w;
q.push(node(v,d[v]));
}
}
}
}
int main()
{
int n,m,u,v,w;
while(~scanf("%d%d",&n,&m) && (n || m))
{
init();
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
Dijkstra(1);
printf("%d\n",d[n]);
}
return 0;
}
```
DFS(因为是求总时间,只需将简单的深搜求最短路的方法,二维数组清零即可):
原始的DFS:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=99999999;//正无穷
int minn;
int n,e[105][105],book[105];
void dfs(int cur,int dis)
{
int j;
//已经超过前面查找的最短路径,就不需要在查找了
if(dis>minn)
return;
if(cur==n)//到达了
{
minn=min(dis,minn);
return;
}
for(j=1;j<=n;j++)//从1号城市到n号城市依次尝试
{//判断当前城市cur到城市j是否有路,并判断城市j是否已经走过
if(e[cur][j]!=INF&&book[j]==0)
{
book[j]=1;//标记已经走过
dfs(j,dis+e[cur][j]);//从城市j再出发,继续寻找
book[j]=0;
}
}
return;
}
int main()
{
int i,j,m,a,b,c;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
//初始化二维矩阵
memset(book,0,sizeof(book));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j) e[i][j]=0;//自己
else e[i][j]=INF;
//读入城市之间的距离
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
e[a][b]=c;
e[b][a]=c;
}
minn=INF;
//从1号城市出发
book[1]=1;
dfs(1,0);
printf("%d\n",minn);
}
return 0;
}
/*
5 8//五个城市,10条路径
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3
*/
修改后的DFS:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 999999;
int minn;
int n,m,e[105][105],book[105];
void dfs(int cur,int dis)
{
int j;
if(dis>minn)
return;
if(cur==n)//到达了终点
{
minn=dis;
return;
}
for(int i=2;i<=n;i++)
{
if(e[cur][i]&&!book[i])
{
book[i]=1;
dfs(i,dis+e[cur][i]);
book[i]=0;//回溯
}
}
return;
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n||m))
{
memset(e,0,sizeof(e));
memset(book,0,sizeof(book));
int a,b,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
e[a][b]=c;
e[b][a]=c;
}
//book[1]=1;
minn=INF;
dfs(1,0);
printf("%d\n",minn);
}
return 0;
}
Dijkstra:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 99999999;
int main()
{
int e[105][105],dis[105],book[105];
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i==j) e[i][j]=0;
else e[i][j]=INF;
int t1,t2,t3;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2]=t3;//双向边
e[t2][t1]=t3;
}
//初始化dis数组,哲理是1号顶点到其余各顶点的初始路程
for(int i=1;i<=n;i++)
dis[i]=e[1][i];
memset(book,0,sizeof(book));//初始化
book[1]=0;//因为1点是源点
int minn,u,v;
//Dijkstra算法核心语句
for(int i=1;i<=n-1;i++)//n-1
{
//找到离1号顶点最近的顶点
//是每次都要找
minn=INF;
for(int j=1;j<=n;j++)
{
if(book[j]==0&&dis[j]<minn)
{
minn=dis[j];
u=j;
}
}
book[u]=1;//一个新的起点
for(v=1;v<=n;v++)
{
if(e[u][v]<INF)
{
if(dis[v]>dis[u]+e[u][v])
dis[v]=dis[u]+e[u][v];
}
}
}
//输出
printf("%d\n",dis[n]);
}
return 0;
}
/*
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
*/
Floyd:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 99999999;
int main()
{
int e[105][105],dis[105],book[105];
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i==j) e[i][j]=0;
else e[i][j]=INF;
int t1,t2,t3;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2]=t3;//双向边
e[t2][t1]=t3;
}
memset(book,0,sizeof(book));//初始化
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
printf("%d\n",e[1][n]);
}
return 0;
}
/*
6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
*/