• [HAOI2012] 道路


    给定一个无向图,一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。(nleq 1500,mleq 5000,wleq 10000)

    Solution

    枚举每个点作为起点,跑出最短路径图,对其拓扑排序后,DP 统计出每个点发出从起点到达该点的最短路的总数,然后扫一遍所有边统计答案即可。

    注意可能有重边

    #include <bits/stdc++.h>
    using namespace std;
    #define reset(x) memset(x,0,sizeof x)
    #define reset3f(x) memset(x,0x3f,sizeof x)
    #define int long long
    const int mod = 1000000007;
    namespace topo {
    const int N=10005;
    vector<int> g[N];
    int n,f[N],h[N],a[N],b[N],c[N],ans[N],vis[N],ind,cnt,s[N];
    void make(int t1,int t2,int t3) {
        g[t1].push_back(t2);
        a[++ind]=t1; b[ind]=t2; c[ind]=t3;
    }
    void dfs(int p) {
        vis[p]=1;
        for(int q:g[p]) {
            if(vis[q]==0) dfs(q);
        }
        s[++cnt]=p;
    }
    void solve(int v0) {
        memset(f,0,sizeof f);
        memset(h,0,sizeof h);
        memset(vis,0,sizeof vis);
        memset(s,0,sizeof s);
        cnt=0;
        f[v0]=1;
        dfs(v0);
        for(int i=cnt;i>=1;i--) {
            int p=s[i];
            for(int q:g[p]) f[q]+=f[p], f[q]%=mod;
        }
        for(int i=1;i<=cnt;i++) {
            int p=s[i]; h[p]++;
            for(int q:g[p]) h[p]+=h[q], h[p]%=mod;
        }
        for(int i=1;i<=ind;i++) {
            ans[c[i]]+=f[a[i]]*h[b[i]]%mod;
            ans[c[i]]%=mod;
        }
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        memset(c,0,sizeof c);
        for(int i=1;i<=n;i++) g[i].clear();
        ind=0;
    }
    }
    
    int ax[10005],bx[10005],cx[10005];
    int n,m,t1,t2,t3;
    
    namespace sp {
    const int N=10005;
    vector<pair<int,int> > g[N];
    int n,v0=1,d[N];
    void make(int t1,int t2,int t3) {
        g[t1].push_back(make_pair(t2,t3));
    }
    void reset_graph() {
        for(int i=0;i<=n;i++) g[i].clear();
    }
    void solve() {
        priority_queue<pair<int,int> > qu;
        reset3f(d);
        d[v0]=0;
        qu.push(make_pair(0,v0));
        while(qu.size()) {
            int p=qu.top().second,r=qu.top().first;
            qu.pop();
            if(r+d[p]) continue;
            for(int i=0;i<g[p].size();i++) {
                int q=g[p][i].first,w=g[p][i].second;
                if(d[q]>d[p]+w) {
                    d[q]=d[p]+w;
                    qu.push(make_pair(-d[q],q));
                }
            }
        }
        for(int i=1;i<=m;i++) {
            if(d[ax[i]]+cx[i]==d[bx[i]]) topo::make(ax[i],bx[i],i);
        }
    }
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        sp::n=topo::n=n;
        for(int i=1;i<=m;i++) {
            cin>>t1>>t2>>t3;
            sp::g[t1].push_back(make_pair(t2,t3));
            ax[i]=t1; bx[i]=t2; cx[i]=t3;
        }
        for(int i=1;i<=n;i++) {
            sp::v0=i;
            sp::solve();
            topo::solve(i);
        }
        for(int i=1;i<=m;i++) cout<<topo::ans[i]<<endl;
    }
    
    
  • 相关阅读:
    golang语法要点笔记
    环境配置
    实现chrome多用户独立cookie
    Golang遇到的问题记录
    php preg_replace去除html xml 注释
    C 基础
    多种写法
    mysql 查看当前数据库
    sql group by
    sql CONCAT()
  • 原文地址:https://www.cnblogs.com/mollnn/p/12388288.html
Copyright © 2020-2023  润新知