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]);
    }
}

 

posted @ 2018-10-17 09:47  Manjusaka丶梦寒  阅读(187)  评论(1编辑  收藏  举报