【题解】JZOJ6578 / 洛谷P5201[USACO2019Jan]Shortcut G

洛谷 P5201 USACO19JAN Shortcut G

题意

在一个带权无向连通图上,每个点有 a i a_i ai 只奶牛,奶牛会走最短路径到 1 1 1,如果有多条路径,选择字典序最小的,定义移动总时间为所有奶牛走到 1 1 1 的时间之和。你可以修建一条从任意一点到 1 1 1 的边权为 t t t 的边,奶牛只有在平时走到 1 1 1 的路上看到这条边才会走。求最多能减少多少移动总时间。

题解

题目保证了对于每个点都有唯一的路径走到 1 1 1,那么可以建出一棵树,根节点为 1 1 1。

然后统计一下子树中奶牛数量总和,对于每个点尝试建时间为 t t t 的新边,可以 O ( 1 ) O(1) O(1) 求出减少的移动总时间。设 j j j 为 i i i 的子树中的节点,则减少的时间为 ( d i s i − t ) ∑ j a j (dis_i-t)\sum\limits_{j}a_j (disi−t)j∑aj。

时间复杂度 O ( n ) O(n) O(n)。

代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50005;
int n, m, t, a[N], vis[N];
LL dis[N], cnt[N], ans = 0;
int cn1 = 0, fi1[N], nx1[N << 1], to1[N << 1], va1[N << 1], cn2 = 0, fi2[N], nx2[N << 1], to2[N << 1];
void ad1(int u, int v, int w) {
	cn1++, nx1[cn1] = fi1[u], fi1[u] = cn1, to1[cn1] = v, va1[cn1] = w; 
	cn1++, nx1[cn1] = fi1[v], fi1[v] = cn1, to1[cn1] = u, va1[cn1] = w;
}
void ad2(int u, int v) { cn2++, nx2[cn2] = fi2[u], fi2[u] = cn2, to2[cn2] = v; }
struct node {
	int r;
	LL dis;
	bool operator < (const node &T) const { return dis > T.dis; }
};
priority_queue<node> pq;
void dij(int r) {
	memset(dis, 0x3f, sizeof(dis)), dis[r] = 0;
	pq.push((node){r, 0});
	while (!pq.empty()) {
		node h = pq.top();
		pq.pop();
		if (vis[h.r]) continue;
		vis[h.r] = 1;
		for (int i = fi1[h.r]; i; i = nx1[i])
			if (dis[to1[i]] > dis[h.r] + va1[i])
				dis[to1[i]] = dis[h.r] + va1[i], pq.push((node){to1[i], dis[to1[i]]});
	}
}
void dfs(int r) {
	cnt[r] = a[r];
	for (int i = fi2[r]; i; i = nx2[i]) dfs(to2[i]);
	for (int i = fi2[r]; i; i = nx2[i]) cnt[r] += cnt[to2[i]];
	if (t < dis[r]) ans = max(ans, (dis[r] - t) * cnt[r]);
}
int main() {
	scanf("%d%d%d", &n, &m, &t);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for (int i = 1, u, v, w; i <= m; i++) scanf("%d%d%d", &u, &v, &w), ad1(u, v, w);
	dij(1);
	for (int i = 2; i <= n; i++) {
		int x = n;
		for (int j = fi1[i]; j; j = nx1[j])
			if (dis[i] == dis[to1[j]] + va1[j])
				x = min(x, to1[j]);
		ad2(x, i);
	}
	dfs(1);
	printf("%lld", ans);
	return 0;
}
相关推荐
牧瀬クリスだ43 分钟前
Redis Hash实战:高效存储对象与购物车
java·数据库·redis·算法·哈希算法
木井巳1 小时前
【动态规划: 路径问题】下降路径最小和
java·算法·leetcode·动态规划·推荐算法
deepseek231 小时前
OpenAI三项科学发现拆解:3-SAT亚指数算法挑战ETH,AI科学声明的验证流水线怎么搭
人工智能·算法·openai
梦帮科技2 小时前
基于幺正李代数连续归一化流的混合量子生成模型 (HQNN-Flow) 完整技术指南(上部分)
网络·人工智能·算法·量子计算
青少儿编程课堂2 小时前
蓝桥杯青少组 + 全国青少年信息素养大赛 + 电子学会图形化考级|校园推箱子大挑战解析
c++·python·算法·bfs·信息学竞赛
荆棘鸟智能2 小时前
河道采砂船识别与轨迹追踪怎么做?检测、跟踪与电子围栏实战思路
人工智能·算法·目标检测
DFT计算杂谈3 小时前
GSAS-II X 射线衍射(XRD)数据转换为对分布函数(PDF,Pair Distribution Function)
算法·机器学习·pdf
绕灵儿3 小时前
火灾检测-应用场景-YOLO训练记录
人工智能·算法
YLCHUP3 小时前
【模拟&STL】题解:AT_abc203_e [ABC203E] White Pawn_基础算法_数据结构_STL模板库_AtcoderABC_C++算法竞赛
数据结构·c++·算法·leetcode·动态规划·哈希算法·近邻算法
(●—●)橘子……4 小时前
力扣 第525场周赛 练习理解
数据结构·python·学习·算法·leetcode