码迷,mamicode.com
首页 > 编程语言 > 详细

[HAOI2012] 道路 - 最短路图,拓扑排序,dp

时间:2020-03-01 10:54:29      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:info   +=   solution   class   img   多少   起点   haoi2012   alt   

给定一个无向图,一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。\(n\leq 1500,m\leq 5000,w\leq 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;
}

[HAOI2012] 道路 - 最短路图,拓扑排序,dp

标签:info   +=   solution   class   img   多少   起点   haoi2012   alt   

原文地址:https://www.cnblogs.com/mollnn/p/12388288.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!