BZOJ 1491: [NOI2007]社交网络
解题思路
数据范围很小,我们考虑floyd。要求的是路径条数,所以我们在floyd的时候直接预处理出两点之间的路径条数。用num[i][j] 表示,然后floyd的时候,如果dis[i][j]
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 105;
const int inf = 0x3f3f3f3f;
typedef long long LL;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
int dis[MAXN][MAXN];
LL num[MAXN][MAXN];
inline void floyd(){
for(register int k=1;k<=n;k++)
for(register int i=1;i<=n;i++)
for(register int j=1;j<=n;j++){
if(dis[i][j]>dis[i][k]+dis[k][j]){
dis[i][j]=dis[i][k]+dis[k][j];
num[i][j]=num[i][k]*num[k][j];
}
else if(dis[i][j]==dis[i][k]+dis[k][j])
num[i][j]+=num[i][k]*num[k][j];
}
}
int main(){
memset(dis,0x3f,sizeof(dis));
n=rd();m=rd();
for(register int i=1;i<=m;i++){
int x=rd(),y=rd(),z=rd();
dis[x][y]=dis[y][x]=z;
num[x][y]=num[y][x]=1;
}
floyd();
// for(register int i=1;i<=n;i++){
// for(register int j=1;j<=n;j++)
// cout<<num[i][j]<<" ";
// cout<<endl;
// }
for(register int k=1;k<=n;k++){
double ans1=0;
for(register int i=1;i<=n;i++){
if(i==k) continue;
for(register int j=1;j<=n;j++){
if(j==k || j==i) continue;
if(dis[i][k]+dis[k][j]==dis[i][j]){
ans1+=(double)(num[i][k]*num[k][j])/(double)num[i][j];
}
}
}
printf("%.3lf\n",ans1);
}
return 0;
}