[NOI2007]社交网络

题目描述

给定 n 个点 m 条边的无向图,定义 $C_{s,t}$ 为 $s 到 t $的最短路条数,$C_{s,t(u)}$ 为经过$ u 的 s 到 t $的最短路条数。对于每个节点$ u$,求$I(u) =∑_{s,t}C_{s,t(u)}/C_{s,t} $

思路

$floyd$求最短路,$dist数组表示最短路长度,sum表示最短路数量,对于i,我们枚举s,t,若dis(s,i)+dis(i,t)=dis(s,t),则可以把答案加到I(i)上$。

code

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=110;
LL dist[N][N];
LL sum[N][N];
int n,m;
double I[N];

int main()
{
    scanf("%d%d",&n,&m);
    memset(dist,127,sizeof(dist));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        LL z;scanf("%d%d%lld",&x,&y,&z);
        sum[x][y]=sum[y][x]=1;
        dist[x][y]=dist[y][x]=min(z,dist[x][y]);
    }
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        if(dist[i][k]==dist[0][0]&&dist[k][j]==dist[0][0])continue;
        if(dist[i][j]==dist[i][k]+dist[k][j])
        {
            sum[i][j]+=sum[i][k]*sum[k][j];
            continue;
        }
        if(dist[i][j]>dist[i][k]+dist[k][j])
        {
            sum[i][j]=sum[i][k]*sum[k][j];
            dist[i][j]=dist[i][k]+dist[k][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int s=1;s<=n;s++)
        for(int t=1;t<=n;t++)
        {
            if(s!=i&&i!=t&&s!=t&&sum[s][t]&&dist[s][t]==dist[s][i]+dist[i][t])
            I[i]+=(1.0*sum[s][i]*sum[i][t])/(1.0*sum[s][t]);
        }
    }
    for(int i=1;i<=n;i++)printf("%.3lf\n",I[i]);
}

 

 

 

 

posted @ 2019-10-02 20:34  EPs1l0h  阅读(181)  评论(0编辑  收藏  举报