【题解】Atcoder ARC#90 E-Avoiding Collision
自己做出来固然开心,但是越发感觉到自己写题的确是很慢很慢了……往往有很多的细节反反复复的考虑才能确定,还要加油呀~
这道题目的突破口在于正难则反。直接求有多少不相交的不好求,我们转而求出所有相交的。我们先预处理出由 \(S\) 到 \(T\) 的最短路图(跑一边Dijkstra,所有的最短路径构成的图),显然可以顺便处理出 \(T\) 到 \(S\) 的。然后这个图是一个拓扑图,满足的性质就是从 \(S\) 点出发的任意一条路径终点均为 \(T\) 且为二者之间的最短路。拓扑图dp对于每个点我们又可以获得 \(Way1[u], Way2[u]\) 分别表示从起点到 \(u\) 点的总路径数和从终点到 \(u\) 的总路径数。
之后我们可以分类讨论一下,两条路径相遇是相遇在点上还是相遇在边上。相遇在点上很好判断,就是从起点到 \(u\) 点的距离正好等于从 \(u\) 点到终点的距离;相遇在边上则要求路径的终点落在这条边上,也是可以 O(1) 判断的。这样就好啦~(๑´ㅂ`๑)
#include <bits/stdc++.h>
using namespace std;
#define maxn 500000
#define mod 1000000007
#define int long long
int n, m, dis1[maxn], dis2[maxn];
int ans, K, S, T, Way1[maxn], Way2[maxn];
bool vis[maxn]; int read()
{
int x = , k = ;
char c; c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct edge
{
int cnp, fr[maxn], to[maxn], co[maxn];
int last[maxn], head[maxn], degree[maxn];
edge() { cnp = ; }
void add(int u, int v, int w = )
{
fr[cnp] = u, to[cnp] = v, co[cnp] = w;
last[cnp] = head[u], head[u] = cnp ++;
}
}E[], G; struct node
{
int x, y;
node(int _x = , int _y = ) { x = _x, y = _y; }
friend bool operator <(const node& a, const node& b)
{ return a.y > b.y; }
}; priority_queue <node> q; void Up(int &x, int y) { x = (x + y) % mod; }
int Qpow(int x) { return x * x % mod; }
void Dijk(int S, int *dis)
{
memset(vis, , sizeof(vis));
dis[S] = ; q.push(node(S, ));
while(!q.empty())
{
node now = q.top(); q.pop();
int u = now.x; if(vis[u]) continue; vis[u] = ;
for(int i = G.head[u]; i; i = G.last[i])
{
int v = G.to[i];
if(dis[v] > dis[u] + G.co[i])
{
dis[v] = dis[u] + G.co[i];
q.push(node(v, dis[v]));
}
}
}
} void Toposort()
{
memset(vis, , sizeof(vis));
queue <int> q; q.push(S);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = G.head[u]; i; i = G.last[i])
{
int v = G.to[i];
if((dis1[u] + dis2[v] + G.co[i]) == K)
{
E[].add(u, v); E[].degree[v] ++;
E[].add(v, u); E[].degree[u] ++;
if(!vis[v]) q.push(v), vis[v] = ;
}
}
}
} void TopoDP(int opt, int *Way)
{
queue <int> q;
for(int i = ; i <= n; i ++)
if(!E[opt].degree[i])
q.push(i), Way[i] = ;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = E[opt].head[u]; i; i = E[opt].last[i])
{
int v = E[opt].to[i];
E[opt].degree[v] --; Up(Way[v], Way[u]);
if(!E[opt].degree[v]) q.push(v);
}
}
} signed main()
{
n = read(), m = read(); S = read(), T = read();
for(int i = ; i <= m; i ++)
{
int x = read(), y = read(), w = read();
G.add(x, y, w), G.add(y, x, w);
}
memset(dis1, , sizeof(dis1)); memset(dis2, , sizeof(dis2));
Dijk(S, dis1), Dijk(T, dis2);
K = dis1[T]; Toposort();
TopoDP(, Way1); TopoDP(, Way2);
for(int i = ; i <= n; i ++)
if(dis1[i] + dis1[i] == K)
Up(ans, Qpow(Way1[i] * Way2[i] % mod) % mod);
for(int i = ; i < E[].cnp; i ++)
{
int u = E[].fr[i], v = E[].to[i];
if(dis1[u] * == K || dis1[v] * == K) continue;
if(K > * dis1[u] && K < * (K - dis2[v]))
Up(ans, Qpow(Way1[u] * Way2[v] % mod) % mod);
}
ans = (Way1[T] * Way1[T] % mod - ans + mod) % mod;
printf("%lld\n", ans);
return ;
}
【题解】Atcoder ARC#90 E-Avoiding Collision的更多相关文章
- 【题解】Atcoder ARC#90 F-Number of Digits
Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...
- [题解] Atcoder ARC 142 D Deterministic Placing 结论,DP
题目 (可能有点长,但是请耐心看完,个人认为比官方题解好懂:P) 首先需要注意,对于任意节点i上的一个棋子,如果在一种走法中它走到了节点j,另一种走法中它走到了节点k,那么这两种走法进行完后,棋子占据 ...
- [题解] Atcoder ARC 142 E Pairing Wizards 最小割
题目 建图很妙,不会. 考虑每一对要求合法的巫师(x,y),他们两个的\(a\)必须都大于\(min(b_x,b_y)\).所以在输入的时候,如果\(a_x\)或者\(a_y\)小于\(min(b_x ...
- AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision
题目传送门:ARC090E. 题意简述: 给定一张有 \(N\) 个点 \(M\) 条边的无向图.每条边有相应的边权,边权是正整数. 小 A 要从结点 \(S\) 走到结点 \(T\) ,而小 B 则 ...
- [题解] Atcoder Regular Contest ARC 147 A B C D E 题解
点我看题 A - Max Mod Min 非常诈骗.一开始以为要观察什么神奇的性质,后来发现直接模拟就行了.可以证明总操作次数是\(O(nlog a_i)\)的.具体就是,每次操作都会有一个数a被b取 ...
- 【题解】Atcoder ARC#96 F-Sweet Alchemy
首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\).既然如此,考虑一棵差分的树,规定每一个节点被选择的次 ...
- 【题解】Atcoder ARC#94 F-Normalization
再次膜拜此强题!神级性质之不可能发现系列收藏++:首先,对于长度<=3的情况,我们采取爆搜答案(代码当中是打表).对于长度>=4的情况,则有如下几条玄妙的性质: 首先我们将 a, b, c ...
- [题解] Atcoder Regular Contest ARC 148 A B C E 题解
点我看题 题目质量一言难尽(至少对我来说 所以我不写D的题解了 A - mod M 发现如果把M选成2,就可以把答案压到至多2.所以答案只能是1或2,只要判断答案能不能是1即可.如果答案是1,那么M必 ...
- [题解] Atcoder Regular Contest ARC 151 A B C D E 题解
点我看题 昨天刚打的ARC,题目质量还是不错的. A - Equal Hamming Distances 对于一个位置i,如果\(S_i=T_i\),那么不管\(U\)的这个位置填什么,对到\(S\) ...
随机推荐
- Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转
Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转 (一)QPixmap和QImage的区别 http://www.thisisqt.com/forum/viewthr ...
- OpenCV 3.2 FlannBasedMatcher
#include <iostream> #include <string> #include <boost/timer.hpp> #include "op ...
- 使用apache cgi运行ruby脚本
在ubuntu下 进入 /usr/lib/cgi-bin目录 新建文件 ruby.cgi 内容如下 #!/usr/bin/ruby print "Content-type: text/htm ...
- Arduino-元件简介
DS18B20温度传感器 DS18B20是DALLAS公司生产的一种常用的温度传感器,其具有体积小巧.硬件功耗低.抗干扰能力强.精准度高的特点.该传感器具有单总线通讯的能力,电压范围为3.0V~5.5 ...
- C# 组装XML传给webserver+XML 返回获取多个xml,根据多个XML 返回dataset类型
大致流程介绍: 传值给 webserver+XML ,得到webserver+XML多个返回值,组装成dataset形式返回 首先创建所需要的类型 DataSet ds = new DataSet() ...
- Qt-QML-全新导航布局
哈哈,写了一个全新的导航布局,具体内容还没有完成,现在先把整个布局的屏幕划分分享出来 先看效果图 身下也没有好说的,看代码 /* 作者:张建伟 时间:2018年4月3日 简述:该文件为下显主窗口布局文 ...
- Linux命令应用大词典-第42章 PostgreSQL数据库
42.1 initdb:初始化PostgreSQL数据库 42.2 pg_ctl:控制PostgreSQL服务 42.3 psql:PostgreSQL交互式客户端工具 42.4 createdb:创 ...
- 【checkbox-group、checkbox】 多项选择器组件说明
checkbox-group组件包裹checkbox组件的容器 原型: <check-group bindchange="[EventHandle]"> <che ...
- git push origin master 错误解决办法
一.错误代码如下: error: failed to push some refs to 'https://github.com/wbingithub/drag.git' 二.在网上搜了一下,如下写就 ...
- Python爬虫模拟登录带验证码网站
问题分析: 1.爬取网站时经常会遇到需要登录的问题,这是就需要用到模拟登录的相关方法.python提供了强大的url库,想做到这个并不难.这里以登录学校教务系统为例,做一个简单的例子. 2.首先得明白 ...