dijkstra算法:
求指定两点间的距离(不适用负边权),O(n^2)
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int INF = 0x3fffffff;
const int MAXV = 105;
int map[MAXV][MAXV], d[MAXV];//map存地图,d存到此点的最短路径
bool vis[MAXV];//存是否访问过
//int pre[MAXV];//pre[k]表示从起点到顶点k的最短路径上k的前一个顶点
//int c[MAXV],cost[MAXV][MAXV];//新增边权 ,边权最小
//int w[MAXV],weight[MAXV];//新增点权 ,w从起点到此点的最大点权 ,点权最大
//int num[MAXV]; //求最短路径条数
void dijkstra(int n, int s)//n为总点数,s为起点
{
fill(vis, vis + MAXV, false);
fill(d, d + MAXV, INF);//初始化为最大
// fill(c, c + MAXV, INF);
//memset(num,0,sizeof(num));
//memset(w,0,sizeof(w));
d[s] = 0;//起点初始化为0
//c[s]=0;
//w[s]=weight[s];
//num[s]=1; //第一个点为 1,别的全为0
for (int i = 0; i < n; i++)//遍历每个点
{
int u = -1, Min = INF;//u使d[u]最小,Min存最小的d[u]
for (int j = 1; j <= n; j++)//寻找未访问点中最小的
{
if (vis[j] == false && d[j] < Min)//寻找最小的点
{
u = j;
Min = d[j];
}
}
if (u == -1)return;//不连通,返回
vis[u] = true;//标记为已访问
for (int k = 1; k <= n; k++)//更新与u点相连接点的最优解
{
//k未访问&&以u为中介点可以使d[k]更优
if (vis[k] == false && map[u][k] != INF)
{
if (d[u] + map[u][k] < d[k])//如果是更优解
{
d[k] = d[u] + map[u][k];
//pre[k]=u;//存前面的点
//c[k]=c[u]+cost[u][k];
//w[k] = w[u] + weight[k];
//num[k] = num[u];
}
/*else if(d[u] + map[u][k] == d[k])//如有第二权值,且需求路径,更新第二权值时更新路径
{
if(w[u]+weight[k]>w[k])//最短距离相同时能使w[k]更优
{
w[k]=w[u]+weight[k];
//pre[k]=u;
}
if(c[u]+cost[u][k]<c[k])//最短距离相同时能使c[k]更优
{
c[k]=c[u]+cost[u][k];
//pre[k]=u;
}
num[k]+=num[u];//最短距离相同时累加num
}
*/
}
}
}
}
/*void dfs(int s,int v)//最短路径只有一条时,输出最短路径
{
if(v==s)
{
printf("%d\n",s);
return;
}
dfs(s,pre[v]);
printf("%d\n",v);
}*/
int main()
{
int i, x, y, z, n, m, s, t;//n为总点数,m为输入路径数
while (scanf("%d %d",&n,&m)!=EOF&&m&&n)
{
fill(map[0], map[0] + MAXV*MAXV, INF);//初始化map
for (i = 1; i <= m; i++)
{
scanf("%d %d %d",&x,&y,&z);
if (map[x][y]>z)//防重边
map[x][y] = map[y][x] = z;//无向边
}
s = 1;//起点
dijkstra(n,s);//s起点为1
t = n;//t为终点
cout << d[t] << endl;//输出终点的最短路径
}
return 0;
}
floyd算法:
可以求出任意两点间的最短距离,O(n^3)
#include<iostream>
#include<cstdio>
using namespace std;
const int INF = 0x3fffffff;
const int MAXV = 1005;
int map[MAXV][MAXV];//map存地图
void floyd(int n)
{
for(int i=1;i<=n;i++)map[i][i]=0; //i到i点初始化为0
for(int k=1;k<=n;k++)//找出一个中介点 使map[i][j]更优
{
for(int i=1;i<=n;i++)
{
if(map[i][k]==INF)continue;//不连通
for(int j=1;j<=n;j++)
if(map[k][j]!=INF&&map[i][k]+map[k][j]<map[i][j])//若通过此点更优
map[i][j]=map[j][i]=map[i][k]+map[k][j];
}
}
}
int main()
{
int i, x, y, z, n, m, s, t;//n为总点数,m为输入路径数
while (scanf("%d %d",&n,&m)!=EOF&&m&&n)
{
fill(map[0], map[0] + MAXV*MAXV, INF);//初始化map
for (i = 1; i <= m; i++)
{
scanf("%d %d %d",&x,&y,&z);
if (map[x][y]>z)//防重边
map[x][y] = map[y][x] = z;//无向边
}
floyd(n);
s=1;//起点
t=n;//终点
cout << map[s][t] << endl;//输出任意两点的最短路径
}
return 0;
}
spfa算法
可用于有负边权
#include<iostream>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x3fffffff;
const int MAXV = 1005;
struct node
{
int v, dis;//v为目标顶点,dis为边权
};
vector<node> adj[MAXV];//图的邻接表
int n, m, d[MAXV], num[MAXV];//d存到此点的最短路径,num记录顶点入队的次数
bool inq[MAXV];//顶点是否在队列中
bool spfa(int s)
{
memset(inq, false, sizeof(inq));
memset(num, 0, sizeof(num));
fill(d, d + MAXV, INF);
queue<int> q;
q.push(s);//源点入队
inq[s] = true;
num[s]++;//源点入队次数加1
d[s] = 0;//源点d值为0
while (!q.empty())
{
int u = q.front();//队首顶点编号u
q.pop();
inq[u] = false;//设u不在队列
for (int j = 0; j<adj[u].size(); j++)//遍历u的所有邻接边v
{
int v = adj[u][j].v;
int dis = adj[u][j].dis;
if (d[u] + dis<d[v])//松弛操作
{
d[v] = d[u] + dis;
if (!inq[v])//如果v不在队列中
{
q.push(v);
inq[v] = true;
num[v]++;
if (num[v] >= n)return false;//有可达负环
}
}
}
}
return true;//无可达负环
}
int main()
{
int cost, a, b, s, t;//a点到b点的花费为cost
node k;//临时结构体,输入用
while (scanf("%d %d", &n, &m) != EOF&&m&&n)
{
for (int i = 0; i < MAXV; i++)
adj[i].clear();
for (int i = 0; i<m; i++)//m为点数,m为输入的边数
{
scanf("%d %d %d", &a, &b, &cost);
k.v = b;
k.dis = cost;
adj[a].push_back(k);//无向边
k.v = a;
adj[b].push_back(k);
}
s = 1;//起点
t = n;//终点
if (spfa(s))printf("%d\n", d[t]);
else printf("出现负环,最短路径不存在\n");
}
}