解题:HAOI 2012 道路

题面

这题不开O2怎么过=。=

可能这种有关最短路的计数题做多了就有些感觉了......

以每个点为基准跑出一张最短路图,然后对每个边$(u,v)$统计两个东西。一个$pre[u]$表示到达$u$这个起点的路径条数,一个$nxt[v]$表示从$v$开始的最短路数,然后对每条边来一下乘法原理。

然后是这两个玩意的统计方法,$pre[]$可以在最短路图上跑拓扑排序得出,$nxt[]$可以跑记忆化搜索,这样统计的复杂度是$O(n+m)$的,总复杂度大概$O(nmlog$ $n)$?然而并不能卡过去......

  1 // luogu-judger-enable-o2
  2 #include<queue>
  3 #include<cstdio>
  4 #include<cctype>
  5 #include<cstring>
  6 #include<algorithm>
  7 using namespace std;
  8 const int N=1505,M=5005;
  9 const long long mod=1e9+7;
 10 struct a{int node,dist;};
 11 bool operator < (a x,a y)
 12 {
 13     return x.dist>y.dist;
 14 }
 15 priority_queue<a> hp;
 16 int dis[N],vis[N],pre[N],nxt[N],deg[N],ans[M],que[N];
 17 int p[N],noww[M],from[M],goal[M],val[M];
 18 int n,m,t1,t2,t3,cnt,f,b;
 19 inline int read()
 20 {
 21     int ret=0;
 22     char ch=getchar();
 23     while(!isdigit(ch))
 24         ch=getchar();
 25     while(isdigit(ch))
 26         ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();
 27     return ret;
 28 }
 29 void link(int f,int t,int v)
 30 {
 31     noww[++cnt]=p[f],p[f]=cnt;
 32     goal[cnt]=t,val[cnt]=v,from[cnt]=f;
 33 }
 34 void Dijkstra(int s)
 35 {
 36     register int i;
 37     memset(vis,0,sizeof vis);
 38     memset(dis,0x3f,sizeof dis);
 39     dis[s]=0,hp.push((a){s,0});
 40     while(!hp.empty())
 41     {
 42         a tt=hp.top(); hp.pop(); int tn=tt.node;
 43         if(vis[tn]) continue ; vis[tn]=true;
 44         for(i=p[tn];i;i=noww[i])
 45             if(dis[goal[i]]>dis[tn]+val[i])
 46             {
 47                 dis[goal[i]]=dis[tn]+val[i];
 48                 hp.push((a){goal[i],dis[goal[i]]});
 49             }
 50     }
 51 }
 52 void getpre(int nde)
 53 {
 54     register int i,j;
 55     for(i=1;i<=n;i++)
 56         for(j=p[i];j;j=noww[j])
 57             if(dis[goal[j]]==dis[i]+val[j]) deg[goal[j]]++;
 58     que[f=b=0]=nde,pre[nde]=1;
 59     while(f<=b)
 60     {
 61         int tn=que[f++];
 62         for(i=p[tn];i;i=noww[i])
 63             if(dis[goal[i]]==dis[tn]+val[i])
 64             {
 65                 pre[goal[i]]+=pre[tn];
 66                 if(!(--deg[goal[i]])) que[++b]=goal[i];
 67             }
 68     }
 69 }
 70 void getnxt(int nde)
 71 {
 72     nxt[nde]=1;
 73     for(int i=p[nde];i;i=noww[i])
 74         if(dis[goal[i]]==dis[nde]+val[i])
 75         {
 76             if(!nxt[goal[i]]) getnxt(goal[i]);
 77             nxt[nde]+=nxt[goal[i]];
 78         }
 79 }
 80 int main ()
 81 {
 82     register int i,j;
 83     scanf("%d%d",&n,&m);
 84     for(int i=1;i<=m;i++)
 85         scanf("%d%d%d",&t1,&t2,&t3),link(t1,t2,t3);
 86     for(i=1;i<=n;i++)
 87     {
 88         Dijkstra(i);
 89         memset(pre,0,sizeof pre);
 90         memset(nxt,0,sizeof nxt);
 91         memset(deg,0,sizeof deg);
 92         getpre(i),getnxt(i);
 93         for(j=1;j<=m;j++)
 94             if(dis[from[j]]+val[j]==dis[goal[j]])
 95                 ans[j]+=1ll*pre[from[j]]*nxt[goal[j]]%mod,ans[j]%=mod;
 96     }
 97     for(i=1;i<=m;i++)
 98         printf("%d\n",ans[i]);
 99     return 0;
100 }

原文地址:https://www.cnblogs.com/ydnhaha/p/9795062.html

时间: 2024-10-10 18:28:55

解题:HAOI 2012 道路的相关文章

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

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

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可以记忆化搜

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] 外星人

[题目链接] 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>

[HAOI 2012] Road

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2750 [算法] 考虑计算每个点对每条边的贡献 对于每个点首先运行SPFA或Dijkstra单源最短路 , 建出以该点为根的最短路树(图) 由于最短路图是一个DAG(有向无环图) , 我们可以求出其拓扑序列 , 对于每个点i , 计算 : CNT1 : 从枚举的点到该点的 , 最短路图上的路径条数 CNT2 : 从该点出发 , 在最短路图上 , 有多少条路径 对于每条在最短路图上的边

汽车电子及ADAS安全部分相关测试标准

标准化已经涉及到了汽车的方方面面,几乎每个重要的零部件都有相关的规定或标准.如火花塞.制动.电子电气.发动机.被动安全.安全玻璃.车轮等等. 更多的标准目录参见: http://www.catarc.org.cn/NewsDetails.aspx?id=1766 在电子电气标准中,ISO 26262规定了道路车辆的功能安全. 目录如下: ISO 26262-1: 2011 道路车辆  功能安全  第1部分:词汇 ISO 26262-2: 2011 道路车辆  功能安全  第2部分:功能安全的管理

2012金华邀请赛解题报告

这次的没学过的算法多了起来.尽管我都猜对了是用什么算法(我仅仅知道大体上各算法的原理,但没写过. .)..还有翻译上的严重失误.这次太慘了... 差点挂零.. 这次比赛的pdf地址:http://poj.org/ProblemDescriptions/jinghua.pdf A题: 题目地址:POJ 4044 因为上次我在低端题上的失误.. 已被队友嫌弃...已经被剥夺写签到题的权利... 可是这题竟然被他俩弄了2小时也没AC. . .于是我不得不把题目又一次翻译了遍,自己敲了代码. 然后AC.

HDU - 2012 素数判定 解题

素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 140168    Accepted Submission(s): 49576 Problem Description 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数. Input 输入