图论最短路问题和最小生成树问题的区别
区别:
一 区别
最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径。
最短路径是从一点出发,到达目的地的路径最小。
图论最短路问题——一个人的旅行
最小生成树问题——Agri-Net
图论最短路
包含dijkstra,spfa,Floyd
最短路dijkstra代码:
//最短路——Dijkstra
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX_V = 205;
int edge[MAX_V][MAX_V] ;
int dis[MAX_V];
bool vis[MAX_V];
int N,A,B;
void Dijkstra()
{
int tmp,pos;
memset(vis,false,sizeof(vis));
for (int i = 1;i <= N;i++)
{
dis[i] = edge[A][i]; //从哪里开始寻找
}
dis[A] = 0;
for (int i = 2;i <= N;i++)
{
tmp = INF; //重新寻找
for (int j = 1;j <= N;j++)
{
if (!vis[j] && tmp > dis[j]) //找到最小的权值
{
tmp = dis[j];
pos = j;
}
}
if (tmp == INF) break; //没有找的,直接进入下一个的寻找
vis[pos] = true; //标记已经找过的点
for (int j = 1;j <= N;j++) //更新周围的点的权值
{
if (dis[pos] + edge[pos][j] < dis[j])
{
dis[j] = dis[pos] + edge[pos][j];
}
}
}
printf("%d
",dis[B] == INF?-1:dis[B]);
}
int main()
{
while (~scanf("%d",&N) && N)
{
int tmp;
for (int i = 0;i <= N;i++)
{
for (int j = 0;j <= i;j++)
{
if (i == j) edge[i][j] = edge[j][i] = 0;
else edge[i][j] = edge[j][i] = INF;
}
}
scanf("%d%d",&A,&B);
for (int i = 1;i <= N;i++)
{
scanf("%d",&tmp);
if (i - tmp > 0)
{
edge[i][i-tmp] = 1;
}
if (i + tmp <= N)
{
edge[i][i+tmp] = 1;
}
}
Dijkstra();
}
return 0;
}
Floyd(不太理解)
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
//实质就是动态规划
最小生成树
一.kruskal算法
二.prim算法
**最小生成树——prim算法**
/*计算最小生成树的一种方法是使其连续地一步步长成。在每一步,都要把一个节点当做根并往上加边,这样也就把相关联的顶点加到增长中的树上。
在算法的任一时刻,我们都可以看到一个已经添加到树上的顶点集,而其余顶点尚未加到这颗树中。此时,算法在每一阶段都可以选择边(u,v),使得(u,v)的值是所有u在树上但v不在树上的边的值中的最小者,而找出一个新的顶点并把它添加到这棵树中。图指出该算法如何从v1开始构建最小生成树。开始时,v1在构建中的树上,它作为树的根但没有边。每一步添加一边和一个顶点到树上。*/
int prim()
{
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
for (int i = 1;i <= N;i++)
{
dis[i] = edge[i][1];
}
dis[1] = 0;
vis[1] = true;
int res = 0;
for (int i = 1;i <= N - 1;i++)
{
int tmp = INF,pos;
for (int j = 1;j <= N;j++)
{
if (!vis[j] && tmp > dis[j])
{
tmp = dis[j];
pos = j;
}
}
if (tmp == INF) return 0;
vis[pos] = true;
res += dis[pos];
for (int j = 1;j <= N;j++)
{
if (!vis[j] && edge[pos][j] < dis[j]) //注意最短路与生成树的更新条件很相似
{
dis[j] = edge[pos][j];
}
}
}
return res;
}