刚开始的时候一直不明白插点的顺序为什么不会对最后的结果有影响----一直不懂这个算法---
今天看见他们都学会了-.-终于把我也带会了--
对于原理的理解我还是通过输出每一步更新后的结果搞明白的
开始一直不懂的是:
对于A-D:
更新B时--AB+BD>AD 不更新
更新C时--AC+CB<AB AB 更新
但是就不能再--AB+BD < AD 来更新了呀--
看了详细的更新过程发现--更新B的时候CB+BD<CD ---CD 就更新了--为40
更新C时就AC+CD<AD ---AD 就更新为60了--
对于任意两个点A,B,如果有A-----a----b------c-----d------B
这条最短路线---不管a,b,c,d 的大小顺序是什么,从1---n----这n个点更新一遍时 就一定可以得到AB的最短距离(在更新a,b,c,d过程中一定把AB连在了一起,不管先连的是 a - c 还是 b - d );
附思路代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int map[100][100];
int n,m;
void pri(int xx)//输出每次更新xx点后的map
{
printf("\n %d:\n",xx);
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
printf("%8d",map[i][j]);
printf("\n");
}
printf("\n\n");
}
int main()
{
n=4,m=5;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (i==j)
map[i][j]=0;
else
map[i][j]=999999;
int a,b,c;
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[a][b]=map[b][a]=min(c,map[a][b]);
}
pri(0);
for (int k=1;k<=n;k++)//k 为i 和 j 点之间插入的点--然后判断 ik + kj 与 ij 的长度大小--来决定是否更新ij的长度
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
map[i][j]=map[j][i]=min(map[i][j],map[i][k]+map[k][j]);
pri(k);
}
return 0;
}
/*
1 2 120
1 3 20
2 3 20
2 4 20
1 4 100
*/
题目链接:poj 1125
题目是问从哪个人开始传播最快--
求出每个人当源头时到其他人的最长时间---谁的最长时间最少就从说开始---
Floyd 求 任意两点的最短距
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int map[120][120];
int n;
void floyd()
{
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
}
int main()
{
while (scanf("%d",&n),n)
{
memset(map,0x3f3f3f,sizeof(map));
for (int i=1;i<=n;i++)
{
int p,a,b;scanf("%d",&p);
for (int j=0;j<p;j++)
{
scanf("%d%d",&a,&b);
map[i][a]=min(map[i][a],b);
}
}
floyd();
int ii=-1,he=0xffffff;
for (int i=1;i<=n;i++)
{
int ans=0;
for (int j=1;j<=n;j++)
{
if (i==j) continue;
ans=max(ans,map[i][j]);
}
if (ans<he)
{
he=ans;ii=i;
}
}
printf("%d %d\n",ii,he);
}
return 0;
}