bzoj1491 [NOI2007]社交网络
https://www.lydsy.com/JudgeOnline/problem.php?id=1491
n那么小我们当然用最喜欢的floyed,(短小而强大)
在处理最短路的的时候,顺便记录一下最短路的数目。
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(dis[i][j]>dis[i][k]+dis[k][j]) { edge[i][j]=edge[i][k]*edge[k][j]; //乘法原理 dis[i][j]=dis[i][k]+dis[k][j]; } else if(dis[i][j]==dis[i][k]+dis[k][j]) //更新最短路 edge[i][j]+=edge[i][k]*edge[k][j]; }
然后还是floyed,这时候判断k点是不是i 到 j最短路上的点,经过k,i到达j的路线也就是(i到k的条数 $\times$ j到k的条数 ),并且统计答案,
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; #define LL long long int n,m; double edge[106][106],dis[106][106],z,ans[106]; int main() { int x,y; memset(dis,0x7f,sizeof(dis)); memset(ans,0,sizeof(ans)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%lf",&x,&y,&z); dis[x][y]=z;dis[y][x]=z; edge[x][y]=1;edge[y][x]=1; } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(dis[i][j]>dis[i][k]+dis[k][j]) { edge[i][j]=edge[i][k]*edge[k][j]; //乘法原理 dis[i][j]=dis[i][k]+dis[k][j]; } else if(dis[i][j]==dis[i][k]+dis[k][j]) //更新最短路 edge[i][j]+=edge[i][k]*edge[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==k||j==k||i==j)continue; //自己到自己为0 if(dis[i][j]==dis[i][k]+dis[k][j]&&edge[i][j]>0) { ans[k]+=edge[i][k]*edge[k][j]/edge[i][j]; //统计答案 } } } printf("%.3lf\n",ans[k]); } }
除特别注明外,本站所有文章均为Manjusaka丶梦寒原创,转载请注明来自出处