1 条题解

  • 0
    @ 2025-8-24 21:34:01

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar GNAQ
    Good:bye

    搬运于2025-08-24 21:34:01,当前版本为作者最后更新于2017-11-01 10:26:41,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    先Floyd求出最短路

    对于每一个点i:

    { 枚举所有点j ,确保i,j联通,且i,j不是一点。

    然后检查有多少点k与j有连边,且在i-j的最短路dis[i][j]上。(也就是检查从i到j有多少条边满足在dis[i][j]上且与j相连)

    esum[j]=1*k , k∈(g[k][j]!=0 && dis[i][k]+g[k][j]==dis[i][j])

    最后考虑DP

    枚举一个终点j,再枚举一个k,如果k在i-j的最短路上,那么esum[k]个方案计入C[i][j]。(有esum[k]条边可以到k点,在最短路上可以选k点,所以要计入方案数目)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<iterator>
    #include<utility>
    #include<queue>
    using namespace std;
    
    int nodenum,edgenum;
    int g[510][510]={0},dis[510][510]={0},fx,wx,tx,C[510][510]={0};
    int esum[510]={0};
    
    inline void readx(int& x)
    {
        x=0;
        register char ch=0; int k=1;
        while (ch<'0' || ch>'9') { ch=getchar(); if (ch=='-') k=-1; }
        while (ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
        x*=k;
    }
    
    void SPFA(int nodex)
    {
        bool vis[510]={0};
        register int prex,u,v;
        queue<int> que;
    
        vis[nodex]=true; dis[nodex][nodex]=0; que.push(nodex);
        while (!que.empty())
        {
            u=que.front(); que.pop();
            vis[u]=false;
            for (register int i=1;i<=nodenum;i++) if (g[u][i])
            {
                if (dis[nodex][i]>dis[nodex][u]+g[u][i])
                {
                    dis[nodex][i]=dis[nodex][u]+g[u][i];
                    if (!vis[i])
                    {
                        que.push(i);
                        vis[i]=true;
                    }
                }
            }
        }
    }
    
    int main()
    {
        memset(dis,0x3f,sizeof(dis));
        readx(nodenum); readx(edgenum);
        for (register int i=1;i<=edgenum;i++)
        {
            readx(fx); readx(tx); readx(wx);
            g[fx][tx]=g[tx][fx]=wx;
        }
        
        for (register int i=1;i<=nodenum;i++) SPFA(i);
        
        //init
        for (register int i=1;i<=nodenum;i++)
        {
            memset(esum,0,sizeof(esum));
            for (register int j=1;j<=nodenum;j++) if (i!=j && dis[i][j]!=dis[0][0])
            {
                for (register int k=1;k<=nodenum;k++) if (g[k][j])
                {
                    if (dis[i][k]+g[k][j]==dis[i][j]) esum[j]++;
                }
            }
            for (register int j=1;j<=nodenum;j++) if (i!=j)
            {
                for (register int k=1;k<=nodenum;k++) if (i!=k)
                {
                    if (dis[i][k]+dis[k][j]==dis[i][j]) C[i][j]+=esum[k];
                }
            }
        }
        
        for (register int i=1;i<=nodenum;i++)
            for (register int j=i+1;j<=nodenum;j++) printf("%d ",C[i][j]);
        
        return 0;
    }
    }
    
    • 1

    信息

    ID
    1080
    时间
    1000~3000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者