【HAOI2012/Luogu2505】道路 最短路DAG

5人阅读 评论(0) 收藏 举报

原题走这里

本题的整个思想十分暴力。
首先,既然最多只有1500个点,那么就可以枚举最短路的起点,然后把最短路的条数累加到各条边上就可以了。
然而,枚举出每一条最短路再累加明显是不现实的,于是我们还需要另一个东西:最短路DAG

最短路DAG,说白了就是由一张图上所有的以某个节点为起始点的最短路构成的图。
或者更加抽象一点就是所有满足dis[v]=dis[u]+a[u][v]的边(u,v)的组成的图。
假如原图没有零环,则该图必然是DAG。
因为既然存在最短路,就不存在负环,而每走过一条边都是在从dis值低端走向dis值高的,不可能一直在上升,因此最短路图必然是DAG。

有了最短路DAG之后就好办了,因为最短路DAG中从源点S开始的所有路径都是最短路。
因此每条边(u,v),经过其的最短路数,为:S到u的最短路数×最短路DAG上由v开始的路径条数。
前者可以在最短路DAG按拓扑序DP求出,
后者可以按照拓扑序倒序DP求出,或者干脆记忆化搜索。

因此,我们的总体思路,就是:
枚举源点,跑SPFA求出最短路DAG,再在最短路DAG上跑两个DP。两个DP一乘,然后各条边分别累加,就AC了。
所以为什么我花了那么久。

具体实现见代码如下:

#include <bits/stdc++.h>
#define MOD 1000000007
using namespace std;
struct edge {
    int u,v,l,p;
} e[5010];
int n,m,top,head[1510],dis[1510],q[7500000],d[1510],w[1510],ret[5010],in[1510];
bool b[1510];
inline bool addedge(int u,int v,int l) {
    e[++top]=(edge) {u,v,l,head[u]};
    head[u]=top;
}
void SPFA(int x) {
    memset(d,0,sizeof(d));
    memset(dis,0x3f,sizeof(dis));
    memset(b,0,sizeof(b));
    register int qh=0,qt=0;
    dis[x]=0;
    q[qt++]=x;
    b[x]=1;
    w[x]=1;
    while(qh<qt) {
        int u=q[qh++];
        b[u]=0;
        for(register int i=head[u]; i; i=e[i].p) {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].l) {
                dis[v]=dis[u]+e[i].l;
                if(!b[v]) {
                    b[v]=1;
                    q[qt++]=v;
                }
            }
        }
    }
    for(int i=1; i<=top; i++) {
        if(dis[e[i].v]==dis[e[i].u]+e[i].l) {
            in[e[i].v]++;
        }
    }
}
void bfs(int x) {
    memset(w,0,sizeof(w));
    register int qh=0,qt=0;
    w[x]=1;
    q[qt++]=x;
    while(qh<qt) {
        int u=q[qh++];
        for(int i=head[u]; i; i=e[i].p) {
            int v=e[i].v;
            if(dis[v]==dis[u]+e[i].l) {
                (w[v]+=w[u])%=MOD;
                if(!--in[v]) {
                    q[qt++]=v;
                }
            }
        }
    }
}
int dp(int x) {
    if(d[x])return d[x];
    d[x]=1;
    for(int i=head[x]; i; i=e[i].p) {
        if(dis[x]+e[i].l==dis[e[i].v]) {
            (d[x]+=dp(e[i].v))%=MOD;
        }
    }
    return d[x];
}
int main() {
//  freopen("roadsw.in","r",stdin);
//  freopen("roadsw.out","w",stdout);
    cin>>n>>m;
    for(int i=1; i<=m; i++) {
        int u,v,l;
        cin>>u>>v>>l;
        addedge(u,v,l);
    }
    for(int i=1; i<=n; i++) {
        SPFA(i);
        bfs(i);
        dp(i);
        for(int j=1; j<=top; j++) {
            if(dis[e[j].u]+e[j].l==dis[e[j].v]) {
                (ret[j]+=(1LL*w[e[j].u]*d[e[j].v])%MOD)%=MOD;
            }
        }
    }
    for(int i=1; i<=top; i++) {
        cout<<ret[i]<<endl;
    }
}
查看评论

CCNP路由实验专题讲解视频课程--路由映射表(route-map)篇

-
  • 1970年01月01日 08:00

[bzoj2750][HAOI2012]Road

2750: [HAOI2012]RoadTime Limit: 10 Sec Memory Limit: 128 MB Submit: 397 Solved: 184 [Submit][Sta...
  • FZHvampire
  • FZHvampire
  • 2015-10-04 19:16:19
  • 874

bzoj 2750: [HAOI2012]Road 最短路+dp

题意C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重...
  • qq_33229466
  • qq_33229466
  • 2017-12-07 21:41:34
  • 107

BZOJ2750 [HAOI2012]Road(最短路)

大神们眼中的水题。。。本蒟蒻搞了一下午。。。Orz。。。 算法就想了半天。。。写代码各种细节错。。。图论太弱怎么办啊T T 注意:题目给的是有向图!!! 【题解】 最短路的性质: 以s为起点,...
  • cjk_cjk
  • cjk_cjk
  • 2015-02-03 17:50:44
  • 1285

UVA - 10917 Walk Through the Forest(最短路的DAG)

题意:Jimmy最近打算穿过一个森林,但是他比较傲娇,于是他决定只走一些特殊的道路,他打算只沿着满足如下条件的(A,B)道路走:存在一条从B出发回家的路,比所有从A出发回家的路径都短。你的任务是计算一...
  • qq_32944513
  • qq_32944513
  • 2017-10-12 18:36:53
  • 79

BZOJ 2752 [HAOI2012]高速公路(road)【线段树

一只又水又裸的线段树 然而flaze太naive于是重写了三次【【跪着望天 前两次算法比较naive……总之就是要求一波前缀和的前缀和,于是ver1写得丑哭,连亲妈flaze都看不下去只好重写,,第二...
  • Flaze_
  • Flaze_
  • 2016-06-04 12:42:24
  • 613

【bzoj 2750】: [HAOI2012]Road

http://www.lydsy.com/JudgeOnline/problem.php?id=2750 首先容易想到枚举点对,可以得到一个O(n^2m)的算法,期望得分60分 ...
  • willinglive
  • willinglive
  • 2015-03-19 16:39:54
  • 708

【BZOJ 2752】 [HAOI2012]高速公路(road)

计数问题+线段树~
  • Regina8023
  • Regina8023
  • 2015-04-20 08:21:14
  • 1374

【bzoj 2749】: [HAOI2012]外星人

http://www.lydsy.com/JudgeOnline/problem.php?id=2749 妈蛋官方数据是错的,害我查半天。。。。 my thoughts: f(x)=0 ...
  • willinglive
  • willinglive
  • 2015-03-19 15:26:54
  • 959

DAG之最短路

引言: DAG:有向无环图。 DAG是学习动态规划的基础,很多问题都可以直接转化为DAG上的最长路、最短路或路径计数问题。 两个经典的DAG模型,嵌套矩形和硬币问题,今天先写第一个嵌套矩形问题。...
  • Rain722
  • Rain722
  • 2016-09-09 20:00:15
  • 776
    个人资料
    持之以恒
    等级:
    访问量: 738
    积分: 336
    排名: 20万+
    文章分类
    文章存档
    最新评论