zoukankan      html  css  js  c++  java
  • bzoj2750最短路计数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2750

    枚举每一个起点,通过该边的子树中有多少节点就知道本次它被经过几次了;

      因为同一起点到该边的起点的最短路唯一。

    但其实不是!就在于可以有长度相等的最短路!

    所以暴力通过dis[cur]+edge[ i ].w==dis[ v ]?来判断该边是否在当前最短路中。

    记录从根到该边起点有多少路径时要保证指向它的点都已赋过值,所以拓扑一下。

    别忘了到处写上那个暴力判断!

    关于rd,别忘了赋初值。只要每次赋rd[cur]=0就行了。其它会在更新dis时赋好。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    const int N=1505,M=5005,mod=1e9+7;
    int n,m,head[N],pre[N],dis[N],xnt,rd[N];
    ll d1[N],d2[N],ans[M];
    bool in[N];
    queue<int> r;
    struct Edge{
        int next,from,to,w;
        Edge(int n=0,int f=0,int t=0,int w=0):next(n),from(f),to(t),w(w) {}
    }edge[M];
    void spfa(int cur)
    {
        memset(dis,1,sizeof dis);
        queue<int> q;
        dis[cur]=0;q.push(cur);in[cur]=1;rd[cur]=0;//
        while(q.size())
        {
            int k=q.front();q.pop();in[k]=0;
            for(int i=head[k],v;i;i=edge[i].next)
            {
                if(dis[k]+edge[i].w==dis[v=edge[i].to])rd[v]++;
                if(dis[k]+edge[i].w<dis[v=edge[i].to])
                {
                    rd[v]=1;
                    dis[v]=dis[k]+edge[i].w;
                    if(!in[v])q.push(v),in[v]=1;
                }
            }
        }
    }
    void dp(int cur)
    {
        d2[cur]=1;
        for(int i=head[cur],v;i;i=edge[i].next)
            if(dis[v=edge[i].to]==dis[cur]+edge[i].w)
            {
                if(!d2[v=edge[i].to])dp(v);
                (d2[cur]+=d2[v])%=mod;
            }
    }
    void tp(int cur)
    {
        r.push(cur);
        for(int i=head[cur],v;i;i=edge[i].next)
            if(dis[v=edge[i].to]==dis[cur]+edge[i].w)//
            {
                rd[v=edge[i].to]--;
                if(!rd[v])tp(v);
            }
    }
    void solve(int cur)
    {
    //    printf("cur=%d
    ",cur);
        memset(d1,0,sizeof d1);
        memset(d2,0,sizeof d2);
        while(r.size())r.pop();
        spfa(cur);
        tp(cur);
        dp(cur);
        d1[cur]=1;
        while(r.size())
        {
            int k=r.front();r.pop();
            for(int i=head[k],v;i;i=edge[i].next)
                if(dis[v=edge[i].to]==dis[k]+edge[i].w)
                    (d1[v]+=d1[k])%=mod;
        }
        for(int i=1,u,v;i<=m;i++)
            if(dis[u=edge[i].from]+edge[i].w==dis[v=edge[i].to])//
            {
                (ans[i]+=d1[u]*d2[v])%=mod;
    //            printf("from=%d to=%d t=%lld ans=%lld
    ",edge[i].from,edge[i].to,d2[edge[i].to],ans[i]);
            }
    }
    int main()
    {
        scanf("%d%d",&n,&m);int x,y,z;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            edge[++xnt]=Edge(head[x],x,y,z);head[x]=xnt;
        }
        for(int i=1;i<=n;i++)
            solve(i);
        for(int i=1;i<=m;i++)
            printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Error: unable to load xmlsec-openssl library
    count(1)、count(*)与count(列名)的执行区别
    Linux下的压缩zip,解压缩unzip命令详解及实例
    linux centos 如何查看操作系统版本信息
    These dependencies were not found: *!!vue-style-loader!css-loader?
    Git如何永久删除某个重要文件文件或文件夹 (包括历史记录) 强制
    LDAP的filter查询详解
    详谈mysqldump数据导出的问题
    GO -- 遍历删除 数组 slice
    mjml强大&&灵活的邮件模版引擎
  • 原文地址:https://www.cnblogs.com/Narh/p/8870576.html
Copyright © 2011-2022 走看看