几乎是瞬间,自己已经是大二了,真得时间过得好快,大一掠过,只有一些美好的回忆留在心头。
不扯淡了,言归正传。
图论,这名字起的太大了,其实就是一些最基本的算法,用于解决图上的最短距离的算法。
第一个是floyd 算法 很简单直白的算法,是使用邻接矩阵来求最短路的算法,其实就是通过点来松弛两点之间的距离。
例如:
for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(g[i][j]>g[i][1]+g[1][j])
g[i][j] = g[i][1]+g[1][j];
}
}
上面的代码就是通过编号为1的这个点来松弛每两个点,缩短他们之间的距离
所以整个核心代码就是:
for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(g[i][j]>g[i][k]+g[k][j])
g[i][j] = g[i][k]+g[k][j];
}
}
}
之后又出现了dijikstra算法(挺难拼的)
这个算法的思路是通过边来实现松弛,它是有一个一维数组dis[] 来储存由1到各个点的距离,首先储存图中的初始距离
然后再进行处理,在这之中,是从那些估计值中选择出最小的值作为源点,因为在这算法中认为所有的边权,都是正值的,所以最小的边已经无法再通过其余的边进行松弛了,所以选其作为源点。(也正由于这思想,这个算法是无法处理带有负权边的图的)
核心代码:
while(sum<n)
{
int temp=maxn;
for(int i=1;i<=n;i++)
{
if(book[i]==0)
{
if(temp>dis[i])
{
temp = dis[i];
cur = i;
}
}
}
book[cur] = 1;
for(int i=1;i<=n;i++)
{
if(g[cur][i]<maxn)
{
if(dis[cur]+g[cur][i]<dis[i])
dis[i] = dis[cur]+g[cur][i];
}
}
sum++;
}
接下来是完美的Bellman-ford算法
算法简单 又 完美的解决了负权边的问题
这个对于图的储存有了变化,它是开了三个数组
u[ ] v[ ] w[ ]
存储各个值
核心代码:
for(int k=1;k<=n-1;k++)
{
for(int i=1;i<=m;i++)
{
if(dis[v[i]]>dis[u[i]]+w[i])
dis[v[i]] = dis[u[i]]+w[i];
}
}
这个算法也是通过边松弛来优化的。当运行完这个循环,在运行一次内循环,所得结果有所变化时,边说明图含有负权边。