BZOJ 2750: [HAOI2012]Road

版权声明:本文为一名蒟蒻的原创文章,大神转载的话顺便说个出处呗。 https://blog.csdn.net/cgh_Andy/article/details/78776521

其实也就是个最短路。。。

以每个点为起点 都跑一次最短路 然后统计一下就好了。。
对于在最短路图上的边(x,y)贡献就是走到x的方案*y有多少种走法走到任意一点
可能比较拗口,随便yy一下就好。。

显然是个有向无环图,正着反着都拓扑一下就能算出来了。。
为了偷懒,我直接按dis排序了,边权>0 这样显然满足拓扑序(不过这样好像就会慢一点…

一开始还因为SB错误WA了一发。。。

#include<bits/stdc++.h>
using namespace std;
const int N=1502,M=5002,mod=1e9+7;
char O[1<<14],*S=O,*T=O;
#define gc (S==T&&(T=(S=O)+fread(O,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
    int x=0,f=1; char ch=gc;
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
    while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+(ch^48); ch=gc;}
    return x*f;
}
struct edg{int y,c,nex;}e1[M],e2[M]; int f1[N],f2[N],len;
void ins(int x,int y,int c){
    e1[++len]=(edg){y,c,f1[x]},f1[x]=len;
    e2[  len]=(edg){x,c,f2[y]},f2[y]=len;
}
int ans[M],fr[N],to[N],d[N],n,a[N];
queue<int>q; bool v[N];
void spfa(int x){
    for(int i=1;i<=n;++i) d[i]=mod,v[i]=0;
    q.push(x); v[x]=1,d[x]=0;
    while(!q.empty()){
        x=q.front(); q.pop(); v[x]=0;
        for(int k=f1[x];k;k=e1[k].nex){
            int y=e1[k].y;
            if(d[y]>d[x]+e1[k].c){
                d[y]=d[x]+e1[k].c;
                if(!v[y]) v[y]=1,q.push(y);
            }
        }
    }
}
int Cmp1(int x,int y){return d[x]<d[y];}
int Cmp2(int x,int y){return d[x]>d[y];}
void solve(int st){
    spfa(st); int i;
    for(i=1;i<=n;++i)fr[i]=0,to[i]=1;
    sort(a+1,a+1+n,Cmp1); fr[st]=1;
    for(i=1;i<=n;++i){
        int x=a[i];
        for(int k=f1[x];k;k=e1[k].nex){
            int y=e1[k].y;
            if(d[y]==d[x]+e1[k].c)fr[y]+=fr[x];
        }
    }
    sort(a+1,a+1+n,Cmp2);
    for(i=1;i<=n;++i){
        int x=a[i];
        for(int k=f2[x];k;k=e2[k].nex){
            int y=e2[k].y;
            if(d[y]+e2[k].c==d[x])to[y]+=to[x];
        }
    }
    for(int x=1;x<=n;++x)
        for(int k=f1[x];k;k=e1[k].nex){
            int y=e1[k].y;
            if(d[y]==d[x]+e1[k].c)
                ans[k]=(ans[k]+1ll*fr[x]*to[y]%mod)%mod;
        }
}
int main(){
    n=read(); int i,m=read();
    for(i=1;i<=m;++i){
        int x=read(),y=read(),c=read();
        ins(x,y,c);
    }
    for(i=1;i<=n;++i)a[i]=i;
    for(i=1;i<=n;++i)
        solve(i);
    for(i=1;i<=m;++i)printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/cgh_Andy/article/details/78776521