首页 > 其他分享 >NC19987 [HAOI2012]ROAD

NC19987 [HAOI2012]ROAD

时间:2023-01-05 20:55:54浏览次数:48  
标签:dpv NC19987 int 短路 条数 ROAD HAOI2012 dp dis

题目链接

题目

题目描述

C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。

输入描述

第一行包含两个正整数n、m
接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路

输出描述

输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果

示例1

输入

4 4
1 2 5
2 3 5
3 4 5
1 4 8

输出

2
3
2
1

备注

30% 的数据满足:\(n\leq 15, m\leq 30\) 。

60% 的数据满足:\(n\leq 300, m\leq 1000\) 。

100% 的数据满足:\(n\leq 1500, m\leq 5000, w\leq 10000\) 。

题解

知识点:最短路,计数dp,拓扑序dp。

为了求出每条边被最短路经过的次数,我们先以每个点出发考虑。

对于某点 \(i\) 为源点,经过一条边 \(u \to v\) 的最短路条数,可以分解为求 \(u\) 为终点的最短路条数,以及 \(v\) 为起点的最短路条数,最后乘在一起就是以 \(i\) 为源点经过这条边的最短路条数。以下是具体步骤:

  1. 先求出以 \(u\) 为终点的最短路条数,可以通过跑最短路时求出。对于一条边 \(u\to v\) ,若 \(dis[v] > dis[u] + w\) ,则 \(dp[v] = dp[u]\) ;若 \(dis[v] = dis[u] + w\) ,则 \(dp[v] = dp[v] + dp[u]\) 。
  2. 随后求出以 \(v\) 为起点的最短路条数,可以从 \(i\) 自底向上dfs求出,。因为最短路图一定是DAG,所以可以进行拓扑序dp。对于某点 \(u\) 的下一个节点 \(v_i\),如果边 $ u \to v_i$ 在最短路上,则先求出以 \(v_i\) 为起点(包括自己为终点,所以初始化 \(dpv[v] = 1\))最短路条数 \(dpv[v_i]\) ,随后可以求出 \(dpv[u] =1+ \sum dpv[v_i]\) ,即以 \(u\) 为起点最短路条数。如果某点以及被计算过了,那就跳过。
  3. 在第二步的同时,我们得到了边 \(u \to v\) 的 \(dp[u]\) 和 \(dpv[v]\) 。那么,这条边以 \(i\) 为源点的答案贡献是 \(dp[u] \cdot dpv[v]\) 。

对每个点都求一遍,累加每条边的贡献即可。

时间复杂度 \(O(n(n+m)\log m)\)

空间复杂度 \(O(n+m)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;
const int N = 1507, M = 5007;

struct edge {
    int v, nxt, w;
}e[M];
int h[N], idx;
void add(int u, int v, int w) {
    e[++idx] = { v,h[u],w };
    h[u] = idx;
}

bool vis[N];
int dis[N];
int dp[N];///起点到i点的最短路总数
struct node {
    int v, w;
    friend bool operator<(const node &a, const node &b) {
        return a.w > b.w;
    }
};
priority_queue<node> pq;
void dijkstra(int s) {
    dis[s] = 0;
    dp[s] = 1;
    pq.push({ s,0 });
    while (!pq.empty()) {
        int u = pq.top().v;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = h[u];i;i = e[i].nxt) {
            int v = e[i].v, w = e[i].w;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                dp[v] = dp[u];
                pq.push(node{ v,dis[v] });
            }
            else if (dis[v] == dis[u] + w) {
                dp[v] = (dp[u] + dp[v]) % mod;
            }
        }
    }
}

int dpv[N];///i点把其他点作为终点的最短路总数
int ans[M];
void dfs(int u) {
    if (dpv[u]) return;
    dpv[u] = 1;///自己作为终点的一种
    for (int i = h[u];i;i = e[i].nxt) {
        int v = e[i].v, w = e[i].w;
        if (dis[v] == dis[u] + w) {
            dfs(v);
            dpv[u] = (dpv[u] + dpv[v]) % mod;
            ans[i] = (ans[i] + 1LL * dp[u] * dpv[v]) % mod;
        }
    }
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1;i <= m;i++) {
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w);
    }
    for (int i = 1;i <= n;i++) {
        for (int j = 1;j <= n;j++) vis[j] = dp[j] = dpv[j] = 0, dis[j] = 0x3f3f3f3f;
        dijkstra(i);
        dfs(i);
    }
    for (int i = 1;i <= m;i++) cout << ans[i] << '\n';
    return 0;
}

标签:dpv,NC19987,int,短路,条数,ROAD,HAOI2012,dp,dis
From: https://www.cnblogs.com/BlankYang/p/17028821.html

相关文章

  • CF671D Roads in Yusland
    CF671DRoadsinYusland第一想法:设\(f_{u,k}\)表示处理完\(u\)子树,向上覆盖到的深度为\(k\)。发现状态数就是平方级别了,而且貌似没有办法直接优化这个状态,那么就考......
  • Flink Shuffle 3.0: Vision, Roadmap and Progress
    摘要:本文整理自阿里云高级技术专家宋辛童(五藏),在FFA2022核心技术专场的分享。本篇内容主要分为五个部分:FlinkShuffle的演进流批融合云原生自适应Shuffle3.0一、Flin......
  • Broadcom 网卡绑定的几种模式(翻译)
     组的类型可以建立4种类型的负载平衡组:智能负载平衡和故障转移链路聚集(802.3ad)(注:不适用于TOE组合)普通中继(FEC/GEC)/802.3ad-DraftStatic(注:不适用于TOE组合)SLB(禁......
  • NumPy broadcasting 广播规则
      https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules BroadcastingSeealsonumpy.broadcastThetermbroadcastingde......
  • Cf1625C Road Optimization
    Cf1625CRoadOptimization题意:在一条长为\(1\)的公路上有\(n\)个路标,第\(i\)个路标在第\(d_i\)米处,限速\(a_i\),意味着在这个路标到下一个路标之间的路段最快......
  • 2019 TRIUMPH ROCKET III ROADSTER SERVICE LAMP RESET
    Background:A2019TRIUMPHROCKETIIIROADSTER,itsmaintenancetimeisup,thedashboardshowsawrenchformaintenancetips.PreparationPreparation: OBDS......
  • Andriod ADB开启Activity、Service以及BroadCast(包括参数的传递)
    /*****************开启Activity并传递参数*******************/​​使用am命令启动Activity并传递参数的方法,也能用作C层与Java进行数据传递的一种手段。​​​​​......
  • BroadcastReceiver应用详解
    今天我们来讲一下Android中BroadcastReceiver的相关知识。(请发邮件到 ​​[email protected]​​  获得最新翻强软件。)BroadcastReceiver也就是“广播接收者”......
  • poj3255 Roadblocks--次短路spfa
    原题链接:​​http://poj.org/problem?id=3255​​题意:n个点,标号为1到n,m条路,u,v,len,表示u与v之间路长为len,求1到n第二短路长,题目保证存在第二短路径。#define_CRT_SECURE_NO_D......
  • WDA学习(27):RoadMap使用
    1.20UIElement:RoadMap使用本实例测试创建RoadMap;运行结果:点击2,Input显示输入航班Id 点击3,根据input输入,查询航班信息 1.创建Component,View:V_ROADMAP;2.......