洛谷 P2505 [HAOI2012]道路 解题报告
P2505 [HAOI2012]道路
题目描述
C国有n座城市,城市之间通过m条单向道路连接。一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小。两条最短路不同,当且仅当它们包含的道路序列不同。我们需要对每条道路的重要性进行评估,评估方式为计算有多少条不同的最短路经过该道路。现在,这个任务交给了你。
输入输出格式
输入格式:
第一行包含两个正整数n、m
接下来m行每行包含三个正整数u、v、w,表示有一条从u到v长度为w的道路
输出格式:
输出应有m行,第i行包含一个数,代表经过第i条道路的最短路的数目对1000000007取模后的结果
说明
30%的数据满足:n≤15、m≤30
60%的数据满足:n≤300、m≤1000
100%的数据满足:n≤1500、m≤5000、w≤10000
题目有两点要说。
一、所有点都能作为起点和终点的最短路-->暴力枚举起点
二、统计确定起点任意终点的最短路上的边出现次数
把问题拆分,找到在这些最短路上的边 和 统计边的出现次数
首先考虑找到最短路上的边和边的两端构成的集合最短路图。
用到两个比较显然的结论:
1.最短路径上的任意一条边都在最短路图上
2.权值都为正的图的最短路图一定不存在环(当有权为0的边就可能存在环了,比如NOIp2017逛公园)
我们可以先跑出最短路,然后枚举边\(E(u,v)\),当\(dis[v]==dis[u]+edge[E(u,v)]\)时,边\(E\)就在最短路图上
关于统计,因为权值都为正无环,所以我们对最短路图考虑topo排序一波
对一条边\(E(u,v)\),如果有\(cnt1\)条路径到\(u\),从\(v\)出去又可以分出\(cnt2\)条路径,则这条边的答案就是\(cnt1*cnt2\)
对于\(cnt1\),其实就是单源的最短路计数。对于\(cnt2\),可以考虑反向建边跑,注意每个点都是起点,所以所有的\(cnt2\)初值都为1
关于卡常:正反图不要嫌麻烦,尽量不要建在一起然后分奇偶边,会T飞的
Code:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#define P pair <int ,int>
#define mod 1000000007
#define rg register
using namespace std;
const int N=1502;
const int M=10010;
int head[N],to[M],edge[M],Next[M],is[M],cnt=1,n,m;
inline void add(int u,int v,int w)//i&1 反向边
{
to[++cnt]=v;edge[cnt]=w;Next[cnt]=head[u];head[u]=cnt;
to[++cnt]=u;edge[cnt]=w;Next[cnt]=head[v];head[v]=cnt;
}
void init()
{
scanf("%d%d",&n,&m);
int u,v,w;
for(rg int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
}
P p;int used[N],dis[N],ans[M];
inline void disj(int s)
{
priority_queue <P,vector <P>,greater <P> > q;
memset(used,0,sizeof(used));
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
p.first=0,p.second=s;
q.push(p);
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(used[u]) continue;
used[u]=1;
for(int i=head[u];i;i=Next[i])
{
if(i&1) continue;
int v=to[i],w=edge[i];
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
p.first=dis[v],p.second=v;
q.push(p);
}
}
}
}
int in1[N],in2[N],cnt1[N],cnt2[N];
inline void New()
{
memset(is,0,sizeof(is));
memset(in1,0,sizeof(in1));
memset(in2,0,sizeof(in2));
for(rg int u=1;u<=n;u++)
for(int i=head[u];i;i=Next[i])
{
if(i&1) continue;
int v=to[i],w=edge[i];
if(dis[u]+w==dis[v]) is[i]=is[i^1]=1,in1[v]++,in2[u]++;
}
}
inline void topo(int s)
{
memset(cnt1,0,sizeof(cnt1));
memset(cnt2,0,sizeof(cnt2));
queue <int > q;
q.push(s);
cnt1[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=Next[i])
{
if(!is[i]||(i&1)) continue;
int v=to[i];
in1[v]--;
(cnt1[v]+=cnt1[u])%=mod;
if(!in1[v]) q.push(v);
}
}
for(rg int i=1;i<=n;i++)
if(!in2[i])
{
cnt2[i]=1;
q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=Next[i])
{
if(!is[i]||!(i&1)) continue;
int v=to[i];
in2[v]--;
(cnt2[v]+=cnt2[u])%=mod;
if(!in2[v]) cnt2[v]++,q.push(v);
}
}
}
inline void cal()
{
for(rg int u=1;u<=n;u++)
for(int i=head[u];i;i=Next[i])
{
if((i&1)||!is[i]) continue;
int v=to[i];
ans[i>>1]=(ans[i>>1]+cnt1[u]*cnt2[v]%mod)%mod;
}
}
void work()
{
for(rg int i=1;i<=n;i++)
{
disj(i);
New();
topo(i);
cal();
}
for(rg int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
int main()
{
init();
work();
return 0;
}
2018.7.15
洛谷 P2505 [HAOI2012]道路 解题报告的更多相关文章
- 洛谷 P1272 重建道路 解题报告
P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...
- 洛谷P2505 [HAOI2012]道路(最短路计数)
传送门 早上模拟赛考这题,结果竟然看错题目了orz 然后下午看完题解自己做的时候空间开小了白WA了好久orz 首先,如果以$S$为起点,一条边$(u,v)$在最短路上,则$dis[u]+edge[i] ...
- 洛谷 P1783 海滩防御 解题报告
P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...
- 洛谷 P4597 序列sequence 解题报告
P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...
- 洛谷1087 FBI树 解题报告
洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...
- 洛谷 P3313 [SDOI2014]旅行 解题报告
P3313 [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教 ...
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- 洛谷 P1850 换教室 解题报告
P1850 换教室 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有\(2n\)节课程安排在\(n\)个时间段上.在第\(i(1≤i≤n) ...
- 洛谷 P1363 幻想迷宫 解题报告
P1363 幻想迷宫 题目描述 背景 Background (喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫.) WD:呜呜,肿么办啊-- LHX:mo ...
随机推荐
- jenkins+jacoco+ant自动化代码和应用服务代码分离场景获取远程服务的覆盖率
前提 自动化代码和应用服务代码分离.jenkins和tomcat服务器分离 思想 1.在tomcat启动javaagent监听. 2.运用其他job_B已部署的应用服务代码 3.拉取自动化代码,开始测 ...
- 用Micro:bit做浇灌系统
利用Micro:bit结合[土壤湿度感测棒]做一个简单的浇灌系统 一.测试土壤湿度感测棒 •材料:土壤湿度感测棒 (万能的淘宝上可以找到) •连接:将[土壤湿度感测棒]的一端接P0.另一端接GND 简 ...
- Qt-QMl-自定义自己想要的TabView
上效果图 上实现源码,这里的代码都是来自Qt官方源码修改其中某一行内容 /* 作者:张建伟 时间:2018年4月8日 简述:自定义TabView,主要实现Tab和实现内容重叠,不在占用独立空间 该文件 ...
- 使用Xamarin实现串口通讯
前几天我写了年度总结,然后有人说让我教一下他Xamarin串口通讯怎么做,其实跟java没有多大区别. 记得我刚开始接到公司这个项目的时候很懵逼,我去看了别的安卓串口工具,都不行我当时是RS232串口 ...
- Spring Cloud(三):服务提供与调用 Eureka【Finchley 版】
Spring Cloud(三):服务提供与调用 Eureka[Finchley 版] 发表于 2018-04-15 | 更新于 2018-05-07 | 上一篇文章我们介绍了 Eureka 服务 ...
- ViewPort <meta>标记
ViewPort <meta>标记用于指定用户是否可以缩放Web页面,如果可以,那么缩放到的最大和最小缩放比例是什么.使用ViewPort <meta>标记还表示文档针对移动设 ...
- mongodb redis memcache 对比
从以下几个维度,对 Redis.memcache.MongoDB 做了对比. 1.性能 都比较高,性能对我们来说应该都不是瓶颈. 总体来讲,TPS 方面 redis 和 memcache 差不多,要大 ...
- Asphalting Roads(翻译!)
Description City X consists of n vertical and n horizontal infinite roads, forming n × n intersectio ...
- KNN算法之图像处理一
KNN: 1.数据挖掘分类技术中最简单的方法之一. 2.也称为邻近算法,K最近邻分类算法 3.每个样本都可以用它最接近的k个邻居来代表 4.一般,距离使用欧式距离或曼哈顿距离(通常,k≤20) pyt ...
- “我爱淘”第二冲刺阶段Scrum站立会议3
完成任务: 完成了注册界面的设计,以及部分代码,但是还没有完成服务器端的添加功能. 计划任务: 将注册功能实现了它,可以对数据库进行添加,在客户端实现分类功能,通过学院的分类查看书籍. 遇到问题: 分 ...