BZOJ 1491: [NOI2007]社交网络(Floyd+暴力乱搞)
题面:
https://www.lydsy.com/JudgeOnline/problem.php?id=1491
题解:
先看数据范围,n<=100。。欸可以乱搞了
首先因为小学学过的乘法原理,a->b有n种走法,b->c有m种走法,那么a->c有n*m种走法。
那么我们就用一个类似邻接矩阵的p矩阵来存走法,p[i][j]表示在最短路的前提下,从i到j的走法。
那么在用floyd跑最短路的时候,如果可以松弛,就用p[i][k]*p[k][j]来更新p[i][j];如果不能松弛,就判断一下如果相等,就由于加法原理,给p[i][j]加上p[i][k]*p[k][j]。
代码:
1 #include<bits/stdc++.h>
2
3 using namespace std;
4
5 typedef long long ll;
6 typedef double dd;
7 const int maxn=110;
8 int n,m,u,v,w;
9 ll g[maxn][maxn],p[maxn][maxn];
10 dd ans[maxn];
11
12 int main(){
13 memset(g,0x3f3f3f3f,sizeof(g));
14 scanf("%d%d",&n,&m);
15 for(int i=1;i<=m;i++)
16 scanf("%d%d%d",&u,&v,&w),g[u][v]=g[v][u]=w,p[u][v]=p[v][u]=1;
17 for(int k=1;k<=n;k++)
18 for(int i=1;i<=n;i++)
19 for(int j=1;j<=n;j++)
20 if(g[i][j]>g[i][k]+g[k][j])
21 g[i][j]=g[i][k]+g[k][j],
22 p[i][j]=p[i][k]*p[k][j];
23 else if(g[i][j]==g[i][k]+g[k][j])
24 p[i][j]+=p[i][k]*p[k][j];
25 for(int k=1;k<=n;k++)
26 for(int i=1;i<=n;i++)
27 for(int j=1;j<=n;j++)
28 if(i!=j&&j!=k&&i!=k&&g[i][k]+g[k][j]==g[i][j])
29 ans[k]+=(dd)p[i][k]*p[k][j]/p[i][j];
30 for(int i=1;i<=n;i++)
31 printf("%.3lf\n",ans[i]);
32 return 0;
33 }