zoukankan      html  css  js  c++  java
  • bzoj 1491 [NOI2007]社交网络

    Floyd

    在之前原有的记录最短路的数组f[i][j]之外,再记录一个数组g[i][j]表示从点i到点j的最短路路径数量

    当转移时枚举的中间节点k,只要f[i][j]被更新,g[i][j]被重置为f[i][k]*f[k][j]

    那当f[i][j]==f[i][k]+f[k][j]时g[i][j]累加通过中间节点k的最短路数量f[i][k]*f[k][j]

    最后枚举每一个点(i),只要其他两点(j,k)到此点的最短路之和等于这两点的最短路,即f[j][i]+f[i][k]==f[j][k]

    那么说明这一点是(j,k)两点最短路可以经过的点,所以累加答案

    还有在做Floyd的时候要注意i,j,k三点不能重复,否则会重复累加答案

    #include <bits/stdc++.h>
    #define ll long long 
    #define inf 1e18
    using namespace std;
    ll n,m,mp[110][110],g[110][110];
    ll f[110][110];
    double ans[110];
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for (ll i=1;i<=n;i++)
        {
            for (ll j=1;j<=n;j++)
            {
                f[i][j]=inf;
            }
            f[i][i]=0;
        }
        for (ll i=1;i<=m;i++)
        {
            ll u,v,len;
            scanf("%lld%lld%lld",&u,&v,&len);
            f[u][v]=len;
            f[v][u]=len;
            g[u][v]=1;
            g[v][u]=1;
        }
        for (ll k=1;k<=n;k++)
        {
            for (ll i=1;i<=n;i++)
            {
                if (i==k)
                  continue;
                for (ll j=1;j<=n;j++)
                {
                    if (i==j && j==k)//注意
                      continue;
                    if (f[i][j]>f[i][k]+f[k][j])
                    {
                        f[i][j]=f[i][k]+f[k][j];
                        g[i][j]=g[i][k]*g[k][j];//覆盖
                    }
                    else
                    if (f[i][j]==f[i][k]+f[k][j])
                    {
                        g[i][j]+=g[i][k]*g[k][j];//累加
                    }
                }
            }
        }
        for (ll i=1;i<=n;i++)
        {
            for (ll j=1;j<=n;j++)
            {
                if (j==i)
                  continue;
                for (ll k=1;k<=n;k++)
                {
                    if (k==i || k==j)
                      continue;
                    if (f[j][k]==f[j][i]+f[i][k])
                      ans[i]+=(g[j][i]*g[i][k]*1.0)/(g[j][k]*1.0);//累加答案
                }
            }
        }
        for (ll i=1;i<=n;i++)
          printf("%.3lf
    ",ans[i]);
    }
  • 相关阅读:
    并查集基础练习
    HDU1232——畅通工程
    二分答案——划分数列
    二分答案——收入计划
    动态规划练习题(2)
    动态规划程序设计2
    动态规划练习题(1)
    0/1背包
    P5024 保卫王国[倍增+dp]
    UVA11424 GCD
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11188568.html
Copyright © 2011-2022 走看看