题目描述
给定 n 个点 m 条边的无向图,定义 $C_{s,t}$ 为 $s 到 t $的最短路条数,$C_{s,t(u)}$ 为经过$ u 的 s 到 t $的最短路条数。对于每个节点$ u$,求$I(u) =∑_{s,t}C_{s,t(u)}/C_{s,t} $
思路
$floyd$求最短路,$dist数组表示最短路长度,sum表示最短路数量,对于i,我们枚举s,t,若dis(s,i)+dis(i,t)=dis(s,t),则可以把答案加到I(i)上$。
code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=110;
LL dist[N][N];
LL sum[N][N];
int n,m;
double I[N];
int main()
{
scanf("%d%d",&n,&m);
memset(dist,127,sizeof(dist));
for(int i=1;i<=m;i++)
{
int x,y;
LL z;scanf("%d%d%lld",&x,&y,&z);
sum[x][y]=sum[y][x]=1;
dist[x][y]=dist[y][x]=min(z,dist[x][y]);
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(dist[i][k]==dist[0][0]&&dist[k][j]==dist[0][0])continue;
if(dist[i][j]==dist[i][k]+dist[k][j])
{
sum[i][j]+=sum[i][k]*sum[k][j];
continue;
}
if(dist[i][j]>dist[i][k]+dist[k][j])
{
sum[i][j]=sum[i][k]*sum[k][j];
dist[i][j]=dist[i][k]+dist[k][j];
}
}
for(int i=1;i<=n;i++)
{
for(int s=1;s<=n;s++)
for(int t=1;t<=n;t++)
{
if(s!=i&&i!=t&&s!=t&&sum[s][t]&&dist[s][t]==dist[s][i]+dist[i][t])
I[i]+=(1.0*sum[s][i]*sum[i][t])/(1.0*sum[s][t]);
}
}
for(int i=1;i<=n;i++)printf("%.3lf
",I[i]);
}