zoukankan      html  css  js  c++  java
  • [HAOI2012]Road


    C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另
    外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进
    行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。
    Input
    第一行包含两个正整数n、m
    接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路
    n≤1500、m≤5000、w≤10000
    Output
    输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果
    Sample Input
    4 4
    1 2 5
    2 3 5
    3 4 5
    1 4 8
    Sample Output
    2
    3
    2
    1

    Sol:针对每个点跑一次最短路,然后算出每条边的入度及出度。

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define ll long long
    #define sqr(x) ((x)*(x))
    #define lowbit(x) (x&(-x))
    #define mid ((l+r)>>1)
    #define ls now<<1,l,mid
    #define rs now<<1|1,mid+1,r
    using namespace std;
    const int N=5010,inf=1e9,p=1e9+7;
    inline int read()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
        return x*f;
    }
    int head[N],tot,dis[N],u,v,w,n,m,cnt,c[N];
    ll a[N],b[N],ans[N];
    struct fk
    {
        int to,nxt,w;
    }e[N];
    struct fq
    {
        int x,v;
        friend bool operator <(fq a,fq b){return a.v>b.v;}
    };
    bool in[N];
    void add(int u,int v,int w)
    {
    e[++cnt].to=v;
    e[cnt].nxt=head[u];
    e[cnt].w=w;
    head[u]=cnt;
    }
    void dijk(int s)
    {
        priority_queue<fq> q;
        memset(dis,63,sizeof(dis));
        memset(in,0,sizeof(in));
        q.push((fq){s,0});
    	dis[s]=0;tot=0;
        while(!q.empty())
    	{
            int x=q.top().x;
    		q.pop();
            if(in[x])continue;
            in[x]=1;
    		c[++tot]=x;
            for(int i=head[x];i;i=e[i].nxt)
                if(dis[e[i].to]>dis[x]+e[i].w)
                    dis[e[i].to]=dis[x]+e[i].w,q.push((fq){e[i].to,dis[e[i].to]}); 
        }
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        a[s]=1;
        for(int i=1;i<=tot;i++)
        	b[c[i]]=1;
        for(int i=1;i<=tot;i++)//取出最短路上的点 
            for(int j=head[c[i]];j;j=e[j].nxt) //j代表从c[i]这个点指出去的边 
                if(dis[c[i]]+e[j].w==dis[e[j].to])
    			   a[e[j].to]=(a[e[j].to]+a[c[i]])%p;//算出每个点的入度 
        for(int i=tot;i;i--)
            for(int j=head[c[i]];j;j=e[j].nxt)
                if(dis[c[i]]+e[j].w==dis[e[j].to])
    			b[c[i]]=(b[c[i]]+b[e[j].to])%p;//算出点的出度 
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=e[j].nxt)
                if(dis[i]+e[j].w==dis[e[j].to])
    			ans[j]=(ans[j]+1LL*a[i]*b[e[j].to]%p)%p;
    }
    int main(){
        n=read();m=read();
        for(int i=1,u,v,w;i<=m;i++)
    	u=read(),v=read(),w=read(),add(u,v,w);
        for(int i=1;i<=n;i++)
         	dijk(i);
        for(int i=1;i<=m;i++)
    	printf("%lld\n",ans[i]);
    }
    

      

  • 相关阅读:
    【读书笔记】程序员的自我修养总结(三)
    【DSP开发】利用CCS5.4开发基于DSP6455的JPEG2000图像解压缩过程
    【DSP开发】利用CCS5.4开发基于DSP6455的JPEG2000图像解压缩过程
    【读书笔记】程序员的自我修养总结(二)
    【读书笔记】程序员的自我修养总结(二)
    【读书笔记】程序员的自我修养总结(一)
    【读书笔记】程序员的自我修养总结(一)
    CMake生成VS2010工程相对路径和绝对路径问题说明
    CMake生成VS2010工程相对路径和绝对路径问题说明
    关于lib和dll
  • 原文地址:https://www.cnblogs.com/cutemush/p/11780217.html
Copyright © 2011-2022 走看看