首先關於Floyd的理解,有一篇博客講的很詳細:
http://www.cnblogs.com/chenying99/p/3932877.html
Floyd從本質上來講是一種DP+滾動數組優化,省去了一維k,即對於已用幾條邊的討論,而在這道題中,所求的是兩點之間經過k點的最短路徑條數,那麼在dp時加上用乘法原理實現的路徑條數統計即可。最後經過k點的條數統計一下即可。
這道題還要注意一個問題,最後統計條數之時,由於是一條路徑,不存在自環的問題,所以i、j、k三者不能相等。
而且還有一個問題,這道題路徑條數統計會爆int,乾脆用double好了。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=105;
int n,m;
int dist[maxn][maxn];
double deno[maxn][maxn];
double res[maxn];
void Floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(dist[i][j]>dist[i][k]+dist[k][j])
{
dist[i][j]=dist[i][k]+dist[k][j];
deno[i][j]=deno[i][k]*deno[k][j];
}
else if(dist[i][j]==dist[i][k]+dist[k][j])
deno[i][j]+=deno[i][k]*deno[k][j];
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&i!=k&&j!=k)
if(dist[i][k]+dist[k][j]==dist[i][j]&&deno[i][j])
res[k]+=(deno[i][k]*deno[k][j])/deno[i][j];
}
int main()
{
scanf("%d%d",&n,&m);
memset(dist,127/3,sizeof dist);
for(int i=1,u,v,val;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&val);
dist[u][v]=dist[v][u]=val;
deno[u][v]=deno[v][u]=1;
}
Floyd();
for(int i=1;i<=n;i++)
printf("%.3lf\n",res[i]);
return 0;
}