Bzoj 1491: [NOI2007]社交网络

这题你看n很小,直接floyd就好了

f[i][j]表示i到j的最短路

注意到

f[i][j]=min{f[i][k]+f[k][j]}

然后我们设c[i][j]为i到j之间的路径长度为f[i][j]的有多少

假设有f[i][k]+f[k][j]=f[i][j]的话

因为i到k之间路径长度为f[i][k]的可能有多条,k到j之间路径长度为f[k][j]的可能有多条

那么根据乘法原理(好像是这东西),乘起来就是i到j之间路径长度为f[i][j]的总条数了

然后怎么统计I(v)的话,看代码吧

 1 #include<cstdio>
 2 #define inf 1*1e9
 3 int n,m,f[105][105];
 4 double cnt[105][105];
 5 double ans[105];
 6 int main() {
 7     scanf("%d%d",&n,&m);
 8     for(int i=1;i<=n;i++)
 9         for(int j=1;j<=n;j++)
10             f[i][j]=(i==j)?0:inf;
11     for(int i=1;i<=m;i++) {
12         int u,v,w;
13         scanf("%d%d%d",&u,&v,&w);
14         f[u][v]=f[v][u]=w;
15         cnt[u][v]=cnt[v][u]=1;
16     }
17     for(int k=1;k<=n;k++)
18         for(int i=1;i<=n;i++)
19         if(i!=k)
20             for(int j=1;j<=n;j++)
21                 if(k!=j&&i!=j) {
22                     if(f[i][k]+f[k][j]<f[i][j]) {
23                         f[i][j]=f[i][k]+f[k][j];
24                         cnt[i][j]=cnt[i][k]*cnt[k][j];
25                     }else 
26                     if(f[i][k]+f[k][j]==f[i][j]) 
27                         cnt[i][j]+=cnt[i][k]*cnt[k][j];
28                 }
29 //    for(int i=1;i<=n;i++)
30 //        for(int j=1;j<=n;j++)
31 //            printf("%d %d %d\n",i,j,f[i][j]);
32     for(int k=1;k<=n;k++)
33         for(int i=1;i<=n;i++)
34         if(i!=k)
35             for(int j=1;j<=n;j++)
36                 if(k!=j&&i!=j) {
37                     if(f[i][k]+f[k][j]==f[i][j]&&cnt[i][j])
38                     ans[k]+=1.000000*cnt[i][k]*cnt[k][j]/cnt[i][j];
39                 }
40     for(int i=1;i<=n;i++)
41         printf("%.3f\n",ans[i]);
42 }
View Code

猜你喜欢

转载自www.cnblogs.com/ZincSabian/p/9390324.html