佛洛伊德算法用于求多源点的最短路径算法~~当然这是最原始的功能。
佛洛伊德算法时间复杂度 为O(n^3)次方。
求最短路,讲的是 如果两点之间的边的距离大于 这两点经过其他点所到达的距离,那么就把最短距离替换成那条经过第三个点所到达的边的距离。(a->b的距离大于a->k->b的距离)a到b的距离大于a经过k再到b(当然这里所说的第三个点不一定就真的是三个点,可能有很多很多个点,见下两张图所示)。请读者仔细阅读,肯定能理解佛洛伊德的流程。
佛洛伊德代码:
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][k]+dis[k][j]<=dis[i][j])
{
dis[i][j]=dis[i][k]+dis[k][j];//当i,j的原来的边的最短距离,大于经过k点所到达的距离那么就替换。
}
}
}
}
}
大家可以练练手了 做道题吧:~~
hdu六度分离。 做下这个题目吧:
/*
思路:
求任意两点之间的最短路,最后只需判断最远两点距离是否大于7即可。
*/
#include
#include
#include
#include
#define MAX 999999
using namespace std;
int map[101][101];
int n,m;
int main()
{
int x,y;
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,k;
memset(map,MAX,sizeof(map));
while(m--)
{
scanf("%d%d",&x,&y);
map[x][y]=map[y][x]=1;
}
for(k=0; k7)
{
printf("No\n");
f=0;
break;
}
}
if(!f)
break;
}
if(f)
printf("Yes\n");
}
return 0;
}
功能2 :求无向图中可以删除一些边,使得任意两点的最短路不改变,求这些边能删除的最大的条数。
这个题
思路是这样:
首先先在输入边的时候将重边去掉,保留最小的。然后根据佛洛依德算法的性质。
如果原来两点的最短距离大于经过第三个点的最短距离的话,那么我们就将这两点的最短距离
替换成经过第三条边的最短距离,因为那个短,既 将这条边替换成经过第三个点的边。
那么原来的边我们就可以删除。
但是~~~当两点之间本来没有边的情况下,我们肯定是经过第三个点所到达的。那么就没有替换
原来的边,这种情况的话,就直接continue
大家可以做下FZU2271
代码:
#include
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
int dis[101][101];
int dis1[101][101];
bool vis[101][101];
int n,m;
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][k]+dis[k][j]<=dis[i][j])
{
dis[i][j]=dis[i][k]+dis[k][j];//当i,j的原来的边的最短距离,大于经过k点所到达的距离那么就替换。
vis[i][j]=1;//当这条边被替换掉,则做好标记
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
int cas=1;
while(t--)
{
scanf("%d%d",&n,&m);
int sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=INF;
}
}
for(int i=1;i<=m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
if(dis[x][y]!=INF)//将重边去掉
{
sum++;
}
if(dis[x][y]>w) dis[x][y]=w,dis[y][x]=w;//选权值最小的边
}
memcpy(dis1,dis,sizeof(dis1));
memset(vis,0,sizeof(vis));
floyd();
for(int i=1;i<=n;i++)
{
for(int j=1;j
题目:URAL - 1004
代码:
#include
#include
#define inf 0x3f3f3f3f
#define maxn 102
int map[maxn][maxn], pre[maxn][maxn];
int dist[maxn][maxn], store[maxn], minCircle;
void getMap(int n, int m)
{
int i, u, v, d;
memset(map, 0x3f, sizeof(map));
for(i = 0; i < m; ++i){
scanf("%d%d%d", &u, &v, &d);
if(d < map[u][v])
map[u][v] = map[v][u] = d;
}
memcpy(dist, map, sizeof(map));
}
void solve(int n)
{
int k, i, j, id, tmp; minCircle = inf;
for(i = 1; i <= n; ++i)
for(j = 1; j <= n; ++j) pre[i][j] = j;//最短路的路径初始化为~~j,表示i到j直接经过j。
for(k = 1; k <= n; ++k){
for(i = 1; i <= k-1; ++i){
for(j = i+1; j <= k-1; ++j)
if( dist[i][j] != inf && map[i][k] != inf &&map[k][j]!=inf&& dist[i][j] + map[i][k] +map[k][j] < minCircle){
minCircle = dist[i][j] + map[i][k] + map[k][j];//此处就是上图的环了。
tmp = i; id = 0;
while(tmp != j){//记录环的路径
store[id++] = tmp;
tmp = pre[tmp][j];
}
store[id++] = j; store[id++] = k;
}
}
for(i = 1; i <= n; ++i)//这里还是求任意两点的最短距离。
for(j = 1; j <= n; ++j)
if(dist[i][k] != inf && dist[k][j] != inf &&
dist[i][k] + dist[k][j] < dist[i][j]){
dist[i][j] = dist[i][k] + dist[k][j];
pre[i][j] = pre[i][k];//记录最短的路径
}
}
if(minCircle == inf){
printf("No solution.\n"); return;
}
for(i = 0; i < id; ++i)
if(i != id - 1) printf("%d ", store[i]);
else printf("%d\n", store[i]);
}
int main()
{
int n, m;
while(scanf("%d", &n)&&n!=-1){
scanf("%d",&m);
getMap(n, m);
solve(n);
}
}