AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision
题目传送门:ARC090E。
题意简述:
给定一张有 \(N\) 个点 \(M\) 条边的无向图。每条边有相应的边权,边权是正整数。
小 A 要从结点 \(S\) 走到结点 \(T\) ,而小 B 则相反,他要从结点 \(T\) 走到结点 \(S\) 。
小 A 和小 B 走一条边需要的时间都是这条边的边权,不论方向。
问有多少种走法,使得他们俩都走了最短路,但是他们不会相遇,这里相遇指的是在点上或者在边上相遇。
答案对 \(10^9+7\) 取模。
题解:
用 Dijkstra 算法求出以结点 \(S\) 和结点 \(T\) 出发到每个点的最短路和最短路条数。
把从结点 \(S\) 到结点 \(i\) 的最短路记作 \(d1_i\) ,最短路条数对 \(10^9+7\) 取模的结果记作 \(g1_i\)。
把从结点 \(T\) 到结点 \(i\) 的最短路记作 \(d2_i\) ,最短路条数对 \(10^9+7\) 取模的结果记作 \(g2_i\)。
把从结点 \(S\) 到结点 \(T\) 的最短路记作 \(Dist\) 。
考虑用容斥的方法计算答案。答案等于总方案数减去相遇的方案数。总方案数为 \(g1_T^2\) 。
因为走的都是最短路,而且边权是正的,不难证明两人只会相遇一次。
所以只要统计在每个点或者每条边经过的方案数即可。
考虑经过结点 \(i\) 的方案数:
前提是 \(d1_i+d2_i=Dist\) 且 \(d1_i=d2_i\) ,方案数为 \(g1_i^2g2_i^2\) 。
考虑经过边 \(i\overset{d}{\Longleftrightarrow}j\) (其中小 A 从结点 \(i\) 走向结点 \(j\) )的方案数:
前提是 \(d1_i+d+d2_i=Dist\) 且 \(d1_i+d>d2_j\) 且 \(d1_i<d+d2_j\) ,方案数为 \(g1_i^2g2_j^2\) 。
#include<bits/stdc++.h>
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#define eF(i,u) for(int i=h[u];i;i=nxt[i])
#define Mod 1000000007
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli; int n,m,S,T;
ll Ans;
int U[],V[],D[];
int h[],nxt[],to[],w[],tot;
void ins(int x,int y,int z){nxt[++tot]=h[x];to[tot]=y;w[tot]=z;h[x]=tot;} ll d1[],d2[],g1[],g2[];bool v1[],v2[];
priority_queue<pli,vector<pli>,greater<pli> > pq; void Dij(ll*d,ll*g,bool*v,int s){
d[s]=0ll;
pq.push(pli(0ll,s));
g[s]=;
while(!pq.empty()){
pli P=pq.top(); pq.pop();
int u=P.second; ll du=P.first;
if(v[u]||d[u]<du) continue;
v[u]=;
eF(i,u){
if(d[to[i]]==du+w[i])
g[to[i]]=(g[to[i]]+g[u])%Mod;
if(d[to[i]]>du+w[i])
g[to[i]]=g[u],
d[to[i]]=du+w[i], pq.push(pli(d[to[i]],to[i]));
}
}
} int main(){
int x,y,z;
scanf("%d%d",&n,&m);
scanf("%d%d",&S,&T);
F(i,,m) scanf("%d%d%d",&x,&y,&z), ins(x,y,z), ins(y,x,z), U[i]=x, V[i]=y, D[i]=z;
memset(d1,0x3f,sizeof d1);
Dij(d1,g1,v1,S);
memset(d2,0x3f,sizeof d2);
Dij(d2,g2,v2,T);
ll Dist=d1[T];
Ans=g1[T]*g1[T]%Mod;
F(i,,n){
if(d1[i]+d2[i]==Dist&&d1[i]==d2[i])
Ans=(Ans-g1[i]*g1[i]%Mod*g2[i]%Mod*g2[i]%Mod)%Mod;
}
int u,v,d;
F(i,,m){
u=U[i], v=V[i], d=D[i];
if(d1[u]+d+d2[v]==Dist && d1[u]+d>d2[v] && d2[v]+d>d1[u]){
Ans=(Ans-g1[u]*g2[v]%Mod*g1[u]%Mod*g2[v]%Mod)%Mod;
}
u=V[i], v=U[i], d=D[i];
if(d1[u]+d+d2[v]==Dist && d1[u]+d>d2[v] && d2[v]+d>d1[u]){
Ans=(Ans-g1[u]*g2[v]%Mod*g1[u]%Mod*g2[v]%Mod)%Mod;
}
}
printf("%lld",(Ans%Mod+Mod)%Mod);
return ;
}
AtCoder ARC 090 E / AtCoder 3883: Avoiding Collision的更多相关文章
- [AtCoder arc090E]Avoiding Collision
Description 题库链接 给出一张 \(N\) 个节点, \(M\) 条边的无向图,给出起点 \(S\) 和终点 \(T\) .询问两个人分别从 \(S\) 和 \(T\) 出发,走最短路不相 ...
- 【题解】Atcoder ARC#90 E-Avoiding Collision
自己做出来固然开心,但是越发感觉到自己写题的确是很慢很慢了……往往有很多的细节反反复复的考虑才能确定,还要加油呀~ 这道题目的突破口在于正难则反.直接求有多少不相交的不好求,我们转而求出所有相交的.我 ...
- 【题解】Atcoder ARC#90 F-Number of Digits
Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...
- AtCoder ARC 076E - Connected?
传送门:http://arc076.contest.atcoder.jp/tasks/arc076_c 平面上有一个R×C的网格,格点上可能写有数字1~N,每个数字出现两次.现在用一条曲线将一对相同的 ...
- AtCoder ARC 076D - Built?
传送门:http://arc076.contest.atcoder.jp/tasks/arc076_b 本题是一个图论问题——Manhattan距离最小生成树(MST). 在一个平面网格上有n个格点, ...
- AtCoder ARC 082E - ConvexScore
传送门:http://arc082.contest.atcoder.jp/tasks/arc082_c 本题是一个平面几何问题. 在平面直角坐标系中有一个n元点集U={Ai(xi,yi)|1≤i≤n} ...
- Atcoder ARC 082C/D
C - Together 传送门:http://arc082.contest.atcoder.jp/tasks/arc082_a 本题是一个数学问题. 有一个长度为n的自然数列a[1..n],对于每一 ...
- 【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)
题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: ...
- 【题解】Atcoder ARC#96 F-Sweet Alchemy
首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\).既然如此,考虑一棵差分的树,规定每一个节点被选择的次 ...
随机推荐
- java 一般类属性设置常量 用以长久使用
java 一般类属性设置常量 用以长久使用 一直引用 例如 文件名
- 将javaweb项目部署到阿里云服务器
主要步骤:1. 购买阿里云服务器2. 远程连接3. 在云服务器上配javaweb环境:jdk,tomcat,MySQL4. 将项目的war文件放到Tomcat下关于云服务器ECS:如果还想在买服务器之 ...
- springmvc+mybatis 根据数据的id删除数据
1. 数据库表 2. notices.jsp <form action="#" method="post"> <fieldset> &l ...
- Vivian's Problem UVA - 1323(梅林素数+状压二进制)
借鉴:https://blog.csdn.net/miku23736748/article/details/52135932 https://blog.csdn.net/acm_cxlove/arti ...
- 【刷题】BZOJ 3732 Network
Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1-N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_ ...
- [NOIP2011]玛雅游戏
闲的没事干,出来写一下早两天刷的一道搜索题NOIP2011玛雅游戏,其实这道题还是比较水的,虽然看起来可能有点复杂. 方法很简单粗暴,直接根据规则模拟就行. 话不多说直接上代码(关键操作在注释中有提到 ...
- CF600E Lomsat gelral 【线段树合并】
题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...
- MySQL事务及隔离级别(读书小结)
标签: MySQL事务 隔离 0.什么是事务? 事务是指MySQL的一些操作看做是一个不可分割的执行单元.事务的特点是要么所有操作都执行成功,要么一个都不执行.也就是如果一个事务有操作执行失败,那么就 ...
- 解题:POI 2014 Ant colony
题面 既然我们只知道最后数量为$k$的蚂蚁会在特殊边上被吃掉,不妨逆着推回去,然后到达每个叶节点的时候就会有一个被吃掉的蚂蚁的区间,然后二分一下就好啦 #include<cstdio> # ...
- php 百家姓
private $surname = array('赵','钱','孙','李','周','吴','郑','王','冯','陈','褚','卫','蒋','沈','韩','杨','朱','秦','尤' ...