[HAOI 2012] Road

[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=2750

[算法]

考虑计算每个点对每条边的贡献

对于每个点首先运行SPFA或Dijkstra单源最短路 , 建出以该点为根的最短路树(图)

由于最短路图是一个DAG(有向无环图) , 我们可以求出其拓扑序列 , 对于每个点i , 计算 :

CNT1 : 从枚举的点到该点的 , 最短路图上的路径条数

CNT2 : 从该点出发 , 在最短路图上 , 有多少条路径

对于每条在最短路图上的边 , 用乘法原理计算贡献即可

时间复杂度 : O(NM)

[代码]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 5010;
const int inf = 2e9;
const int P = 1e9 + 7;

struct edge
{
        int to , w , nxt;
} e[N << 1];

int n , m , tot;
int dist[N] , cnta[N] , cntb[N] , u[N] , v[N] , w[N] , head[N] , topo[N] , ans[N];
bool ok[N];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘;
    x *= f;
}
inline void addedge(int u , int v , int w)
{
        ++tot;
        e[tot] = (edge){v , w , head[u]};
        head[u] = tot;
}
inline void spfa(int S)
{
        static bool inq[N];
        queue< int > q;
        for (int i = 1; i <= n; ++i)
        {
                dist[i] = inf;
                inq[i] = false;
                cnta[i] = cntb[i] = 0;
        }
        for (int i = 1; i <= m; ++i) ok[i] = false;
        q.push(S);
        inq[S] = true;
        dist[S] = 0;
        while (!q.empty())
        {
                int cur = q.front();
                q.pop();
                inq[cur] = false;
                for (int i = head[cur]; i; i = e[i].nxt)
                {
                        int v = e[i].to , w = e[i].w;
                        if (dist[cur] + w < dist[v])
                        {
                                dist[v] = dist[cur] + w;
                                if (!inq[v])
                                {
                                        inq[v] = true;
                                        q.push(v);
                                }
                        }
                }
        }
        for (int i = 1; i <= m; ++i)
                if (dist[u[i]] + w[i] == dist[v[i]]) ok[i] = true;
}
inline void calc()
{
        queue< int > q;
        static int deg[N];
        for (int i = 1; i <= n; ++i)
                deg[i] = 0;
        for (int i = 1; i <= m; ++i)
                if (ok[i]) ++deg[v[i]];
        for (int i = 1; i <= n; i++)
                if (!deg[i])
                {
                        cnta[i] = 1;
                        q.push(i);
                }
        int M = 0;
        while (!q.empty())
        {
                int cur = q.front();
                q.pop();
                topo[++M] = cur;
                for (int i = head[cur]; i; i = e[i].nxt)
                {
                        int v = e[i].to;
                        if (!ok[i]) continue;
                        cnta[v] = (cnta[v] + cnta[cur]) % P;
                        if (!(--deg[v])) q.push(v);
                }
        }
        for (int i = n; i >= 1; i--)
        {
                ++cntb[topo[i]];
                for (int j = head[topo[i]]; j; j = e[j].nxt)
                {
                        int v = e[j].to;
                        if (!ok[j]) continue;
                        cntb[topo[i]] = (cntb[topo[i]] + cntb[v]) % P;
                }
        }
}
inline void update(int S)
{
        spfa(S);
        calc();
        for (int i = 1; i <= m; ++i)
                if (ok[i]) ans[i] = (ans[i] + 1ll * cnta[u[i]] * cntb[v[i]] % P) % P;
}

int main()
{

        read(n); read(m);
        for (int i = 1; i <= m; ++i)
        {
                read(u[i]); read(v[i]); read(w[i]);
                addedge(u[i] , v[i] , w[i]);
        }
        for (int i = 1; i <= n; ++i) update(i);
        for (int i = 1; i <= m; ++i) printf("%d\n" , ans[i]);

        return 0;

}

原文地址:https://www.cnblogs.com/evenbao/p/10540041.html

时间: 2024-11-09 01:42:56

[HAOI 2012] Road的相关文章

BZOJ 2750 HAOI 2012 Road 高速公路 最短路

题意: 给出一个有向图,求每条边有多少次作为最短路上的边(任意的起始点). 范围:n <= 1500, m <= 5005 分析: 一个比较容易想到的思路:以每个点作为起点,做一次SPFA,记f[i]表示从点S到达点i的最短路数,g[i]表示从点i到达点T的最短路数. 那么对于任意一条边,答案就是∑f[u]*g[v] 剩下的问题就是f.g怎么求. f必须从前面的递推过来,如果前面的没有递推完,那么就不能递推当前点,需要记录每个点可以从多少个点递推过来,这个一次dfs就可以完成. g可以记忆化搜

NOIp2014模拟赛8 河南省选(HAOI 2012)

地址见 BZOJ  2748~2750 Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改变的音量是多少.每一次改变音量,他可以选择调高也可以调低. 音量用一个整数描述.输入文件中给定整数beginLevel,代表吉他刚开始的音量,以及整数maxLevel,代表吉他的最大音量.音量不能小于0也不能大于maxLevel.输入文件中还给定了n个整数c1

BZOJ 2751 HAOI 2012 容易题(easy) 数学

题目大意:给出一个序列中哪个位置不能出现哪一种数字,求可以组成的数列的积的和. 思路:如果我们让第一个位置确定,那么这个问题就可以转化成一个子问题.也就是第一位的数字乘上后面的积的和.推下去的话不难发现,其实求得就是每一位和的积.观察一下mn都很大,之后k不大,于是就用个map啥的随便记录一下,然后写个快速幂,再写个快速乘,没了.. CODE: #include <map> #include <cstdio> #include <cstring> #include &l

[HAOI 2012]音量调节

Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改变的音量是多少.每一次改变音量,他可以选择调高也可以调低.音量用一个整数描述.输入文件中给定整数beginLevel,代表吉他刚开始的音量,以及整数maxLevel,代表吉他的最大音量.音量不能小于0也不能大于maxLevel.输入文件中还给定了n个整数c1,c2,c3…..cn,表示在第i首歌开始

解题:HAOI 2012 道路

题面 这题不开O2怎么过=.= 可能这种有关最短路的计数题做多了就有些感觉了...... 以每个点为基准跑出一张最短路图,然后对每个边$(u,v)$统计两个东西.一个$pre[u]$表示到达$u$这个起点的路径条数,一个$nxt[v]$表示从$v$开始的最短路数,然后对每条边来一下乘法原理. 然后是这两个玩意的统计方法,$pre[]$可以在最短路图上跑拓扑排序得出,$nxt[]$可以跑记忆化搜索,这样统计的复杂度是$O(n+m)$的,总复杂度大概$O(nmlog$ $n)$?然而并不能卡过去..

[HAOI 2012] 外星人

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2749 [算法] 首先 , 每次对一个数x进行操作 , 只会使该数减少一个2的因子 那么 , 我们只需考虑每个数可以分解为多少个2 : 设gi表示i可以分解为多少个2 当gi为质数时 : gi = gi-1 否则 , 若gi = ab , 则gi = g(a) + g(b) 线性筛预处理即可 时间复杂度 : O(N + TM) [代码] #include<bits/stdc++.h>

[SinGuLaRiTy] COCI 2011~2012 #2

[SinGuLaRiTy-1007] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 测试题目 对于所有的题目:Time Limit:1s  |  Memory:256 MB 第一题:考试得分(score)[najboljih] [题目描述] 某单位举办了一次考试,考试有8道题,每道题的得分不一样.选手可以随便做,但最后只统计5道题的得分.现在给出选手每道题的得分,求出他最后的得分最大是多少? [输入] 8行,每行一个正整数X(0<=X<

(转)The Road to TensorFlow

Stephen Smith's Blog All things Sage 300… The Road to TensorFlow – Part 7: Finally Some Code leave a comment » Introduction Well after a long journey through Linux, Python, Python Libraries, the Stock Market, an Introduction to Neural Networks and tr

Inventium Presys 2012 R3 1CD

CAE.Datamine.Studio.v3.23.52.0 1CD 矿山软件CAE.NPV.Scheduler.v4.22.250.0 1CD(原名Datamine)矿山开采优化软件 LARS Bridge 06.00.01.07 Win32_64 2CD Mentor Graphics PADS VX.0 Windows 1DVD Portable MAPC2MAPC v5.3.5 Win32_64 2CD SolidCAM 2014 SP2 HF1 for SolidWorks 2012-