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;
}
posted @ 2018-07-09 19:24  Monster_Qi  阅读(102)  评论(0编辑  收藏  举报