首页 > 其他分享 >【P2505】今天开始我要自己上厕所 爸爸妈妈你们不要小看我 宝宝巴士教我上厕所秘诀 我等不及了 我要上厕所

【P2505】今天开始我要自己上厕所 爸爸妈妈你们不要小看我 宝宝巴士教我上厕所秘诀 我等不及了 我要上厕所

时间:2023-12-23 15:46:19浏览次数:48  
标签:idx int ll P2505 我要 maxn dis 厕所 out

题目传送门

不管怎么说,双倍经验


题意很简洁了。

对于每个源点 \(s\),先跑一遍 dijkstra。显然,若满足 \(dis_v=dis_u+w_{u,v}\),则 \(e(u,v)\) 一定在最短路上。

显然在 \(w_{u,v}>0\) 时,不存在 \(u,v\) 使得 \(dis_u=dis_v+w_{u,v} \wedge dis_v=dis_u+w_{u,v}\)。

因此,若将最短路径上的点从原图中取出,加入集合 \(V\),其构成的图一定为 DAG \(G(V,E)\)。

可以考虑将其进行拓扑排序。

一般来说是可以在 dijkstra 中排序的。但是如果你硬要再写一遍也没人拦你

然后捏?

图上 dp。

设 \(G(V,E)\) 的源点(集)为 \(s'\),汇点(集)为 \(t'\)。

对于任意 \(E_i:e(u,v)\),设 \(out_i\) 为 \(s'\to u\) 的方案数,\(in_i\) 为 \(v\to t'\) 的方案数。

根据乘法原理,得 \(ans_i=in_i\times out_i\)。

\(out_i\) 好求。转移方程为 \(out_u=out_u+out_v[dis_u+w_{u,v}=dis_v]\ \ e(u,v)\in E\)。

事实上 \(in_i\) 和 \(out_i\) 的求法是一样的。

将 \(v\to t'\) 这部分建个反图 \(G'(V',E')\) 就可以达到同样的效果。

转移方程为 \(in_u=in_u+in_v[dis_v+w_{u,v}=dis_u]\ \ e(u,v)\in E'\)。


代码实现:

#include <bits/stdc++.h>
typedef long long ll;
const int maxn = 15020, maxm = 50020;
const int inf = 998244853;
const int mod = 1e9 + 7;
class Solution {
	struct Graph {
		struct edge {
			int u, v, w, next;
		};
		int head[maxn], idx;
		edge e[maxm];
		void add(int x, int y, int z) {
			idx++; e[idx].u = x, e[idx].v = y, e[idx].w = z;
			e[idx].next = head[x], head[x] = idx;
		}
	} G, revG; 
	struct point {
		int u; ll dis;
		point(int a, ll b) {u = a, dis = b;}
		friend bool operator < (point a, point b) {
			return a.dis > b.dis;
		}
	};
	int n, m;
	std::vector <int> route;
	ll ans[maxn];
	ll dis[maxn];
	bool mk[maxn];
	ll in[maxn], out[maxn];
	void dijkstra(int st, Graph &G) {
		std::priority_queue <point> q;
		for(int i = 1; i <= n; i++) dis[i] = inf, mk[i] = 0;
		dis[st] = 0, q.push(point(st, 0));
		while(!q.empty()) {
			int u = q.top().u; q.pop();
			if(mk[u]) continue;
			mk[u] = 1; route.push_back(u);
			for(int j = G.head[u]; j; j = G.e[j].next) {
				int v = G.e[j].v, w = G.e[j].w;
				if(dis[v] > dis[u] + w) dis[v] = dis[u] + w, q.push(point(v, dis[v]));
			}
		}
	}
	void Count(int st) {
		dijkstra(st, G);
		for(int i = 1; i <= n; i++) in[i] = 0, out[i] = 0;
		in[st] = 1;
		for(auto v : route) {
			for(int i = revG.head[v]; i; i = revG.e[i].next) {
				int u = revG.e[i].v, w = revG.e[i].w;
				if(dis[v] == dis[u] + w) in[v] += in[u], in[v] %= mod;
			}
		}
		std::reverse(route.begin(), route.end());
		for(auto u : route) {
			out[u] = 1;
			for(int i = G.head[u]; i; i = G.e[i].next) {
				int v = G.e[i].v, w = G.e[i].w;
				if(dis[v] == dis[u] + w) out[u] += out[v], out[u] %= mod;
			}
		}
		route.clear();
		for(int i = 1; i <= m; i++) {
			int u = G.e[i].u, v = G.e[i].v, w = G.e[i].w;
			if(dis[v] == dis[u] + w) ans[i] += std::max(1ll, in[u]) * std::max(1ll, out[v]), ans[i] %= mod;
		}
	}
	public: void solve() {
		scanf("%d %d", &n, &m);
		for(int i = 1; i <= m; i++) {
			int u, v, w;
			scanf("%d %d %d", &u, &v, &w);
			G.add(u, v, w), revG.add(v, u, w);
		}
		for(int i = 1; i <= n; i++) Count(i);
		for(int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
	}
} S;
int main() {
	S.solve();
	return 0;
}

标签:idx,int,ll,P2505,我要,maxn,dis,厕所,out
From: https://www.cnblogs.com/CQWDX/p/17923182.html

相关文章

  • 2023-12-14 早就想写的,关于自己的不敢索取,不敢要,别人问我要,很烦躁
    2023-12-14   本想记录下之前把一个微信好友删了的事情。拖延了一段时间。   一个佛友,老问我索取,问我借钱,要钱。我感觉不耐烦,就删了。我为什么不耐烦?一则是前先时候确实没钱,给不起。另外我给别人没什么问题,别人问我要,我就不太愿意给。   我不敢索取,不敢要。别......
  • Linux越学越头疼,我要怎么办?
    最近,听到一些同学说,“Linux越学越头疼”。其实这句话,在我之前刚接触Linux的时候,也是深有感触。Linux越学越不明所以。最后干脆放弃学习,转而学习其他东西。其实大家在初学Linux的时候,有这个感受,也是十分正常和普遍的。我们大家从一开始接触计算机,便一直是Windows系统,从未使用过Li......
  • Linux越学越头疼,我要怎么办?
      最近,听到一些同学说,“Linux越学越头疼”。其实这句话,在我之前刚接触Linux的时候,也是深有感触。Linux越学越不明所以。最后干脆放弃学习,转而学习其他东西。其实大家在初学Linux的时候,有这个感受,也是十分正常和普遍的。我们大家从一开始接触计算机,便一直是Windows系统,从未使......
  • Linux越学越头疼,我要怎么办?
    最近,听到一些同学说,“Linux越学越头疼”。其实这句话,在我之前刚接触Linux的时候,也是深有感触。Linux越学越不明所以。最后干脆放弃学习,转而学习其他东西。其实大家在初学Linux的时候,有这个感受,也是十分正常和普遍的。我们大家从一开始接触计算机,便一直是Windows系统,从未使用过Li......
  • PAT_B1003 我要通过!
    “答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送——只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。得到“答案正确”的条件是:字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;任意形如 xPA......
  • 呜呜呜我要拿Go赢他~ Go language MacOs build development environment Hello! Go !
    前言Go编程语言是一个开源项目,旨在提高程序员的工作效率。Go富有表现力、简洁、干净且高效。它的并发机制使编写能够充分利用多核和联网机器的程序变得容易,而其新颖的类型系统可以实现灵活和模块化的程序构建。Go可以快速编译为机器代码,同时还具有垃圾收集的便利性和运行时反射......
  • 「杂文」身为 OIer 的我要在第 7 周速通《汇编语言》,我为什么会做这样的梦(雾)
    目录写在前面计算斐波那契数列第\(i\)项写在最后写在前面编译器为MASM-v6.11写的一坨屎。计算斐波那契数列第\(i\)项最多支持输出30位十进制数。为第22行的cx寄存器赋值即为所求的项。.modellargeassumecs:code,ss:stackstringsegmentdb30dup(0),......
  • “我要找到你”——主动救助,让乡村重疾儿童看病不再“两眼一抹黑”
    走出医院,主动寻找郑小伟是河北省阜平县妇幼保健院的儿科主任,在这里工作快20年了。从2021年11月开始,她的桌上一直摆着厚厚一叠阜平县重疾儿童住院名单。她对着上面的名字一个个打电话,手机打不通,就换座机再接着打。很多家属以为她是骗子,直接就给挂了。她在电话里跟对方解释:我们这里有......
  • 我要开始做USACO的DP以对抗智力下降
    P6205[USACO06JAN]DollarDayzS-洛谷|计算机科学教育新生态(luogu.com.cn)题解:完全背包,__int128,傻逼题#include<bits/stdc++.h>usingnamespacestd;__int128f[10001];voidwrite(__int128x){if(x>9)write(x/10);putchar(x%10+'0');}intmain(......
  • 【NOIP模拟题】我要的幸福 题解
    1.题意简述\(Zyh\)相信自己想要的幸福在不远处。然而,\(zyh\)想要得到这幸福,还需要很长的一段路。\(Zyh\)坚持认为整个人生可以抽象为一个\(n*m\)的棋盘。左上角的格子为\((1,1)\),右下角的格子为\((n,m)\)。整个棋盘上的格子都有不同的事件,因为生活的多姿多彩,事件的权值......