Skip to content

Commit 97c8821

Browse files
author
robot
committed
feat: $3108
1 parent 3a37db3 commit 97c8821

File tree

5 files changed

+176
-6
lines changed

5 files changed

+176
-6
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,16 @@ leetcode 题解,记录自己的 leetcode 解题之路。
554554
- [2030. 含特定字母的最小子序列](./problems/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.md)
555555
- [2102. 序列顺序查询](./problems/2102.sequentially-ordinal-rank-tracker.md)
556556
- [2141. 同时运行 N 台电脑的最长时间](./problems/2141.maximum-running-time-of-n-computers.md)
557+
- [2179. 统计数组中好三元组数目](./problems/2179.count-good-triplets-in-an-array.md) 👍
557558
- [2209. 用地毯覆盖后的最少白色砖块](./problems/2209.minimum-white-tiles-after-covering-with-carpets.md) 👍
558559
- [2281. 巫师的总力量和](./problems/2281.sum-of-total-strength-of-wizards.md)
559560
- [2306. 公司命名](./problems/2306.naming-a-company.md) 枚举优化好题
561+
- [2312. 卖木头块](./problems/2312.selling-pieces-of-wood.md) 动态规划经典题
560562
- [2842. 统计一个字符串的 k 子序列美丽值最大的数目](./problems/2842.count-k-subsequences-of-a-string-with-maximum-beauty.md)
561563
- [2972. 统计移除递增子数组的数目 II](./problems/2972.count-the-number-of-incremovable-subarrays-ii.md)
562564
- [3027. 人员站位的方案数 II](./problems/3027.find-the-number-of-ways-to-place-people-ii.md)
563565
- [3041. 修改数组后最大化数组中的连续元素数目 ](./problems/3041.maximize-consecutive-elements-in-an-array-after-modification.md)
564-
- [5254. 卖木头块](./problems/5254.selling-pieces-of-wood.md) 动态规划经典题
565-
- [5999. 统计数组中好三元组数目](./problems/5999.count-good-triplets-in-an-array.md) 👍
566+
- [3108. 带权图里旅途的最小代价](./problems/3108.minimum-cost-walk-in-weighted-graph.md)
566567

567568
## :trident:  anki 卡片
568569

SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,15 @@
366366
- [2030. 含特定字母的最小子序列](./problems/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.md)
367367
- [2102. 序列顺序查询](./problems/2102.sequentially-ordinal-rank-tracker.md)
368368
- [2141. 同时运行 N 台电脑的最长时间](./problems/2141.maximum-running-time-of-n-computers.md)
369+
- [2179. 统计数组中好三元组数目](./problems/2179.count-good-triplets-in-an-array.md) 👍
369370
- [2209. 用地毯覆盖后的最少白色砖块](./problems/2209.minimum-white-tiles-after-covering-with-carpets.md)
370371
- [2281.sum-of-total-strength-of-wizards](./problems/2281.sum-of-total-strength-of-wizards.md)
371372
- [2306. 公司命名](./problems/2306.naming-a-company.md) 枚举优化好题
373+
- [2312. 卖木头块](./problems/2312.selling-pieces-of-wood.md) 动态规划经典题
372374
- [2842. 统计一个字符串的 k 子序列美丽值最大的数目](./problems/2842.count-k-subsequences-of-a-string-with-maximum-beauty.md)
373375
- [2972. 统计移除递增子数组的数目 II](./problems/2972.count-the-number-of-incremovable-subarrays-ii.md)
374376
- [3027. 人员站位的方案数 II](./problems/3027.find-the-number-of-ways-to-place-people-ii.md)
375377
- [3041. 修改数组后最大化数组中的连续元素数目 ](./problems/3041.maximize-consecutive-elements-in-an-array-after-modification.md)
376-
- [5254. 卖木头块](./problems/5254.selling-pieces-of-wood.md) 动态规划经典题
377-
- [5999. 统计数组中好三元组数目](./problems/5999.count-good-triplets-in-an-array.md) 👍
378+
- [3108. 带权图里旅途的最小代价](./problems/3108.minimum-cost-walk-in-weighted-graph.md)
378379

379380
- [后序](epilogue.md)

problems/5999.count-good-triplets-in-an-array.md renamed to problems/2172.count-good-triplets-in-an-array.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 题目地址(5999. 统计数组中好三元组数目)
1+
## 题目地址(2179. 统计数组中好三元组数目)
22

33
https://leetcode-cn.com/problems/count-good-triplets-in-an-array/
44

problems/5254.selling-pieces-of-wood.md renamed to problems/2312.selling-pieces-of-wood.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 题目地址(5254. 卖木头块)
1+
## 题目地址(2312. 卖木头块)
22

33
https://leetcode.cn/problems/selling-pieces-of-wood/
44

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
2+
## 题目地址(3108. 带权图里旅途的最小代价 - 力扣(LeetCode))
3+
4+
https://leetcode.cn/problems/minimum-cost-walk-in-weighted-graph/
5+
6+
## 题目描述
7+
8+
<p>给你一个 <code>n</code>&nbsp;个节点的带权无向图,节点编号为 <code>0</code>&nbsp;到 <code>n - 1</code>&nbsp;。</p>
9+
10+
<p>给你一个整数 <code>n</code>&nbsp;和一个数组&nbsp;<code>edges</code>&nbsp;,其中&nbsp;<code>edges[i] = [u<sub>i</sub>, v<sub>i</sub>, w<sub>i</sub>]</code>&nbsp;表示节点&nbsp;<code>u<sub>i</sub></code> 和&nbsp;<code>v<sub>i</sub></code>&nbsp;之间有一条权值为&nbsp;<code>w<sub>i</sub></code>&nbsp;的无向边。</p>
11+
12+
<p>在图中,一趟旅途包含一系列节点和边。旅途开始和结束点都是图中的节点,且图中存在连接旅途中相邻节点的边。注意,一趟旅途可能访问同一条边或者同一个节点多次。</p>
13+
14+
<p>如果旅途开始于节点 <code>u</code>&nbsp;,结束于节点 <code>v</code>&nbsp;,我们定义这一趟旅途的 <strong>代价</strong>&nbsp;是经过的边权按位与 <code>AND</code>&nbsp;的结果。换句话说,如果经过的边对应的边权为&nbsp;<code>w<sub>0</sub>, w<sub>1</sub>, w<sub>2</sub>, ..., w<sub>k</sub></code>&nbsp;,那么代价为<code>w<sub>0</sub> &amp; w<sub>1</sub> &amp; w<sub>2</sub> &amp; ... &amp; w<sub>k</sub></code>&nbsp;,其中&nbsp;<code>&amp;</code>&nbsp;表示按位与&nbsp;<code>AND</code>&nbsp;操作。</p>
15+
16+
<p>给你一个二维数组&nbsp;<code>query</code>&nbsp;,其中&nbsp;<code>query[i] = [s<sub>i</sub>, t<sub>i</sub>]</code>&nbsp;。对于每一个查询,你需要找出从节点开始&nbsp;<code>s<sub>i</sub></code>&nbsp;,在节点&nbsp;<code>t<sub>i</sub></code>&nbsp;处结束的旅途的最小代价。如果不存在这样的旅途,答案为&nbsp;<code>-1</code>&nbsp;。</p>
17+
18+
<p>返回数组<em>&nbsp;</em><code>answer</code>&nbsp;,其中<em>&nbsp;</em><code>answer[i]</code><em>&nbsp;</em>表示对于查询 <code>i</code>&nbsp;&nbsp;<strong>最小</strong>&nbsp;旅途代价。</p>
19+
20+
<p>&nbsp;</p>
21+
22+
<p><strong class="example">示例 1:</strong></p>
23+
24+
<div class="example-block">
25+
<p><span class="example-io"><b>输入:</b>n = 5, edges = [[0,1,7],[1,3,7],[1,2,1]], query = [[0,3],[3,4]]</span></p>
26+
27+
<p><span class="example-io"><b>输出:</b>[1,-1]</span></p>
28+
29+
<p><strong>解释:</strong></p>
30+
31+
<p><img alt="" src="https://assets.leetcode.com/uploads/2024/01/31/q4_example1-1.png" style="padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem; width: 351px; height: 141px;"></p>
32+
33+
<p>第一个查询想要得到代价为 1 的旅途,我们依次访问:<code>0-&gt;1</code>(边权为 7 )<code>1-&gt;2</code>&nbsp;(边权为 1 )<code>2-&gt;1</code>(边权为 1 )<code>1-&gt;3</code>&nbsp;(边权为 7 )。</p>
34+
35+
<p>第二个查询中,无法从节点 3 到节点 4 ,所以答案为 -1 。</p>
36+
37+
<p><strong class="example">示例 2:</strong></p>
38+
</div>
39+
40+
<div class="example-block">
41+
<p><span class="example-io"><b>输入:</b>n = 3, edges = [[0,2,7],[0,1,15],[1,2,6],[1,2,1]], query = [[1,2]]</span></p>
42+
43+
<p><span class="example-io"><b>输出:</b>[0]</span></p>
44+
45+
<p><strong>解释:</strong></p>
46+
47+
<p><img alt="" src="https://assets.leetcode.com/uploads/2024/01/31/q4_example2e.png" style="padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem; width: 211px; height: 181px;"></p>
48+
49+
<p>第一个查询想要得到代价为 0 的旅途,我们依次访问:<code>1-&gt;2</code>(边权为 1 ),<code>2-&gt;1</code>(边权 为 6 ),<code>1-&gt;2</code>(边权为 1 )。</p>
50+
</div>
51+
52+
<p>&nbsp;</p>
53+
54+
<p><strong>提示:</strong></p>
55+
56+
<ul>
57+
<li><code>1 &lt;= n &lt;= 10<sup>5</sup></code></li>
58+
<li><code>0 &lt;= edges.length &lt;= 10<sup>5</sup></code></li>
59+
<li><code>edges[i].length == 3</code></li>
60+
<li><code>0 &lt;= u<sub>i</sub>, v<sub>i</sub> &lt;= n - 1</code></li>
61+
<li><code>u<sub>i</sub> != v<sub>i</sub></code></li>
62+
<li><code>0 &lt;= w<sub>i</sub> &lt;= 10<sup>5</sup></code></li>
63+
<li><code>1 &lt;= query.length &lt;= 10<sup>5</sup></code></li>
64+
<li><code>query[i].length == 2</code></li>
65+
<li><code>0 &lt;= s<sub>i</sub>, t<sub>i</sub> &lt;= n - 1</code></li>
66+
</ul>
67+
68+
69+
## 前置知识
70+
71+
-
72+
73+
## 公司
74+
75+
- 暂无
76+
77+
## 思路
78+
79+
由于代价是按位与 ,而不是相加,因此如果 s 到 t 我们尽可能多的走,那么 and 的值就会越来越小。这是因为两个数的与一定不比这两个数大。
80+
81+
- 考虑如果 s 不能到达 t,那么直接返回 -1。
82+
- 如果 s 到 t 可以到达,说明 s 和 t 在同一个联通集。对于联通集外的点,我们无法到达。而对于联通集内的点,我们可以到达。前面说了,我们尽可能多的做,因此对于联通集内的点,我们都走一遍。答案就是联通集合中的边的 and 值。
83+
84+
使用并查集模板可以解决,主要改动点在于 `union` 方法。大家可以对照我的并查集标准模板看看有什么不同。
85+
86+
## 关键点
87+
88+
-
89+
90+
## 代码
91+
92+
- 语言支持:Python3
93+
94+
Python3 Code:
95+
96+
```python
97+
98+
99+
class UF:
100+
def __init__(self, M):
101+
self.parent = {}
102+
self.cnt = 0
103+
self.all_and = {}
104+
# 初始化 parent,size 和 cnt
105+
# Initialize parent, size and cnt
106+
for i in range(M):
107+
self.parent[i] = i
108+
self.cnt += 1
109+
self.all_and[i] = 2 ** 30 - 1 # 也可以初始化为 -1
110+
111+
def find(self, x):
112+
if x != self.parent[x]:
113+
self.parent[x] = self.find(self.parent[x])
114+
return self.parent[x]
115+
return x
116+
def union(self, p, q, w):
117+
# if self.connected(p, q): return # 这道题对于联通的情况不能直接 return,具体可以参考示例 2. 环的存在
118+
leader_p = self.find(p)
119+
leader_q = self.find(q)
120+
self.parent[leader_p] = leader_q
121+
# p 连通块的 and 值为 w1,q 连通块的 and 值为 w2,合并后就是 w1 & w2 & w
122+
self.all_and[leader_p] = self.all_and[leader_q] = self.all_and[leader_p] & w & self.all_and[leader_q]
123+
self.cnt -= 1
124+
def connected(self, p, q):
125+
return self.find(p) == self.find(q)
126+
127+
class Solution:
128+
def minimumCost(self, n: int, edges: List[List[int]], query: List[List[int]]) -> List[int]:
129+
g = [[] for _ in range(n)]
130+
uf = UF(n)
131+
for x, y, w in edges:
132+
g[x].append((y, w))
133+
g[y].append((x, w))
134+
uf.union(x, y, w)
135+
136+
ans = []
137+
for s, t in query:
138+
if not uf.connected(s, t):
139+
ans.append(-1)
140+
else:
141+
ans.append(uf.all_and[uf.parent[s]])
142+
return ans
143+
144+
145+
146+
147+
```
148+
149+
150+
**复杂度分析**
151+
152+
令 m 为 edges 长度。
153+
154+
- 时间复杂度:$O(m + n)$
155+
- 空间复杂度:$O(m + n)$
156+
157+
158+
159+
160+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
161+
162+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
163+
164+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
165+
166+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
167+
168+
![](https://p.ipic.vip/h9nm77.jpg)

0 commit comments

Comments
 (0)