2023-02-14:魔物了占领若干据点,这些据点被若干条道路相连接,
roads[i] = [x, y] 表示编号 x、y 的两个据点通过一条道路连接。
现在勇者要将按照以下原则将这些据点逐一夺回:
在开始的时候,勇者可以花费资源先夺回一些据点,
初始夺回第 j 个据点所需消耗的资源数量为 cost[j]
接下来,勇者在不消耗资源情况下,
每次可以夺回一个和「已夺回据点」相连接的魔物据点,
并对其进行夺回。
为了防止魔物暴动,勇者在每一次夺回据点后(包括花费资源夺回据点后),
需要保证剩余的所有魔物据点之间是相连通的(不经过「已夺回据点」)。
请返回勇者夺回所有据点需要消耗的最少资源数量。
输入保证初始所有据点都是连通的,且不存在重边和自环。
输入:cost = [1,2,3,4,5,6],roads = [[0,1],[0,2],[1,3],[2,3],[1,2],[2,4],[2,5]]。
输出:6。

答案2023-02-24:

代码用rust编写。代码如下:

执行结果如下:

use std::iter::repeat;
fn main() {
let cost = vec![1, 2, 3, 4, 5, 6];
let roads = vec![
vec![0, 1],
vec![0, 2],
vec![1, 3],
vec![2, 3],
vec![1, 2],
vec![2, 4],
vec![2, 5],
];
let ans = unsafe { Solution::minimum_cost(cost, roads) };
println!("ans = {:?}", ans);
} struct Solution {} impl Solution {
pub fn minimum_cost(cost: Vec<i32>, roads: Vec<Vec<i32>>) -> i64 {
let mut roads = roads;
let n = cost.len() as i32;
if n == 1 {
return cost[0] as i64;
}
let m = roads.len() as i32;
let mut dc = DoubleConnectedComponents::new(n, m, &mut roads);
let mut ans: i64 = 0;
// dcc {a,b,c} {c,d,e}
if dc.dcc.len() == 1 {
ans = i64::MAX;
for num in cost.iter() {
ans = get_min(ans, *num as i64);
}
} else {
// 不只一个点双连通分量
let mut arr: Vec<i32> = vec![];
for set in dc.dcc.iter() {
let mut cutCnt = 0;
let mut curCost = i32::MAX;
for nodes in set.iter() {
if dc.cut[*nodes as usize] {
cutCnt += 1;
} else {
curCost = get_min(curCost, cost[*nodes as usize]);
}
}
if cutCnt == 1 {
arr.push(curCost);
}
}
arr.sort_by(|a, b| a.partial_cmp(b).unwrap());
for i in 0..arr.len() as i32 - 1 {
ans += arr[i as usize] as i64;
}
}
return ans;
}
} fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
} struct DoubleConnectedComponents {
// 链式前向星建图
head: Vec<i32>,
next: Vec<i32>,
to: Vec<i32>, dfn: Vec<i32>,
low: Vec<i32>,
stack: Vec<i32>,
dcc: Vec<Vec<i32>>,
cut: Vec<bool>,
edgeCnt: i32,
dfnCnt: i32,
top: i32,
root: i32,
}
impl DoubleConnectedComponents {
pub fn new(n: i32, m: i32, roads: &mut Vec<Vec<i32>>) -> Self {
let mut ans = DoubleConnectedComponents {
head: vec![],
next: vec![],
to: vec![], dfn: vec![],
low: vec![],
stack: vec![],
dcc: vec![],
cut: vec![],
edgeCnt: 0,
dfnCnt: 0,
top: 0,
root: 0,
};
ans.init(n, m);
ans.createGraph(roads);
ans.creatDcc(n);
ans
} fn init(&mut self, n: i32, m: i32) {
let t = repeat(-1).take(n as usize).collect::<Vec<i32>>();
self.head = t;
let t = repeat(0).take((m << 1) as usize).collect::<Vec<i32>>();
self.next = t;
let t = repeat(0).take((m << 1) as usize).collect::<Vec<i32>>();
self.to = t;
let t = repeat(0).take(n as usize).collect::<Vec<i32>>();
self.dfn = t;
let t = repeat(0).take(n as usize).collect::<Vec<i32>>();
self.low = t;
let t = repeat(0).take(n as usize).collect::<Vec<i32>>();
self.stack = t;
let t = repeat(false).take(n as usize).collect::<Vec<bool>>();
self.cut = t;
self.edgeCnt = 0;
self.dfnCnt = 0;
self.top = 0;
self.root = 0;
} fn createGraph(&mut self, roads: &mut Vec<Vec<i32>>) {
for edges in roads.iter() {
self.add(edges[0], edges[1]);
self.add(edges[1], edges[0]);
}
} fn add(&mut self, u: i32, v: i32) {
self.to[self.edgeCnt as usize] = v;
self.next[self.edgeCnt as usize] = self.head[u as usize];
self.head[u as usize] = self.edgeCnt;
self.edgeCnt += 1;
} fn creatDcc(&mut self, n: i32) {
for i in 0..n {
// 0 1 2 3 n-1
if self.dfn[i as usize] == 0 {
self.root = i;
self.tarjan(i);
}
}
} fn tarjan(&mut self, x: i32) {
self.dfnCnt += 1;
self.low[x as usize] = self.dfnCnt;
self.dfn[x as usize] = self.low[x as usize];
self.stack[self.top as usize] = x;
self.top += 1;
let mut flag = 0;
if x == self.root && self.head[x as usize] == -1 {
self.dcc.push(vec![]);
let t = (self.dcc.len() as i32 - 1) as usize;
self.dcc[t].push(x);
} else {
// 当前来到的节点是x
// x {a,b,c}
let mut i = self.head[x as usize];
while i >= 0 {
// y是下级节点
let mut y = self.to[i as usize];
if self.dfn[y as usize] == 0 {
// y点没遍历过!
self.tarjan(y);
if self.low[y as usize] >= self.dfn[x as usize] {
// 正在扎口袋
flag += 1;
if x != self.root || flag > 1 {
self.cut[x as usize] = true;
}
let mut curAns: Vec<i32> = vec![];
// 从栈里一次弹出节点
// 弹到y停!
// 弹出的节点都加入集合,x也加入,x不弹出
self.top -= 1;
let mut z = self.stack[self.top as usize];
while z != y {
curAns.push(z);
self.top -= 1;
z = self.stack[self.top as usize];
}
curAns.push(y);
curAns.push(x);
self.dcc.push(curAns);
}
self.low[x as usize] = get_min(self.low[x as usize], self.low[y as usize]);
} else {
// y点已经遍历过了!
self.low[x as usize] = get_min(self.low[x as usize], self.dfn[y as usize]);
}
i = self.next[i as usize];
}
}
}
}

2023-02-14:魔物了占领若干据点,这些据点被若干条道路相连接, roads[i] = [x, y] 表示编号 x、y 的两个据点通过一条道路连接。 现在勇者要将按照以下原则将这些据点逐一夺回:的更多相关文章

  1. LinkedIn的即时消息:在一台机器上支持几十万条长连接

    最近我们介绍了LinkedIn的即时通信,最后提到了分型指标和读回复.为了实现这些功能,我们需要有办法通过长连接来把数据从服务器端推送到手机或网页客户端,而不是许多当代应用所采取的标准的请求-响应模式 ...

  2. Sql语句中两个比较迷糊的概念:“连接查询” 与 “外键约束”

    Sql语句中两个比较迷糊的概念:“连接查询” 与 “外键约束 Sql 中的连接查询:就是为了避免笛卡尔积,因为涉及到多表查询的化,不使用连接查询,会先将多个互相乘,求出笛卡尔积,然后在在里面查询符合的 ...

  3. 计算机网络:TCP协议建立连接的过程为什么是三次握手而不是两次?【对于网上的两种说法我的思考】

    网上关于这个问题吵得很凶,但是仔细看过之后我更偏向认为两种说的是一样的. 首先我们来看看 TCP 协议的三次握手过程 如上图所示: 解释一下里面的英文: 里面起到作用的一些标志位就是TCP报文首部里的 ...

  4. TCP 两次握手为什么无法阻止历史连接?

    摘要:在两次握手的情况下,「被动发起方」没有中间状态给「主动发起方」来阻止历史连接,导致「被动发起方」可能建立一个历史连接,造成资源浪费. 本文分享自华为云社区<TCP 两次握手为什么无法阻止历 ...

  5. 2019.02.14 codechef Chef at the Food Fair(线段树+泰勒展开)

    传送门 题意:现在有nnn个位置,每个位置上有一个值aia_iai​. 要求支持如下两种操作: 区间乘vvv 求区间的(1−ai)(1-a_i)(1−ai​)之积 思路: 考虑转换式子: Ans=∏i ...

  6. 2016.02.14 总结JS事件

    今天主要总结JS事件的基本知识以及使用技巧,并作出相应的DEMO.

  7. Html5 reset表 2015年1月7日15:02:14

    /* HTML5 Reset :: style.css ---------------------------------------------------------- We have learn ...

  8. NO.009-2018.02.14《临江仙·送钱穆父》宋代:苏轼

    临江仙·送钱穆父_古诗文网 临江仙·送钱穆父 宋代:苏轼 一别都门三改火,天涯踏尽红尘.依然一笑作春温.无波真古井,有节是秋筠.自从我们在京城分别一晃又三年,远涉天涯你奔走辗转在人间.相逢一笑时依然像 ...

  9. 梦想Android版CAD控件(安卓CAD二次开发,安卓CAD控件)2023.02.26更新

    下载地址:https://www.mxdraw.com/ndetail_40240.html1. 增加willBeReturnStart事件2. 增加使用OpenGL缓存3. 优化界面响应时间4. 修 ...

  10. MxDraw云图平台(H5在线CAD) 网页CAD,网页查看CAD图纸,2023.02.26更新

    下载地址:https://www.mxdraw.com/ndetail_40241.html1. 梦想服务上传CAD文件格式转换,增加转换后的文件例表返回2. 增加绘制图片Tag功能3. 修改在一些图 ...

随机推荐

  1. 转帖:巧用Stream优化老代码,太清爽了!

    Java8的新特性主要是Lambda表达式和流,当流和Lambda表达式结合起来一起使用时,因为流申明式处理数据集合的特点,可以让代码变得简洁易读 放大招,流如何简化代码 如果有一个需求,需要对数据库 ...

  2. 在VS中C#工程操作Mysql数据库

    1.实现mysql数据库与VS的连接,需要安装两个插件,作者装的是mysql-connector-net-6.9.9.msi和 mysql-for-visualstudio-1.2.6.msi. 2. ...

  3. luffy前端配置and跨域

    1. 安装axios 命令:npm install axios main.js内配置并使用 import axios from 'axios'app.config.globalProperties.$ ...

  4. Nacos的微服务与本地测试的问题

    前提条件: 这里是微服务上的yml的配置: uri: base-svc-authcenter: 192.168.1.121:28002 base-svc-file: 192.168.1.121:280 ...

  5. 开源不易、安全慎行,中国软件如何走向文明?丨RTE 技术环境月报 202205

    各位开发者小伙伴: 这里是 2022 年第 5 期的 RTE<技术环境月报>--致力于成为对大家"有用"的 Highlight 看板--每月初通过 RTC 开发者社区( ...

  6. MyBatisPlus映射匹配兼容性

    字段映射与表名映射 1.当数据库表名tbl_user与实体类名User不一致时:在实体类上添加 :@TableName("tbl_user") package com.itheim ...

  7. 《HelloTester》第3期

    1.前言 读了之前的简历篇和投递篇,你应该开始准备迎接面试了,那么,在面试前,我们都需要准备些什么呢?是要默默的去背诵那些理论知识,还是熟悉一下自己的技能?又或者去看看公司要求的那些技术呢?接下来这篇 ...

  8. 为什么HashMap查找比List快很多?

    做两数之和这道题目时,引发了一个思考: 为什么两者运行时间相差如此之大???好残忍,我List比你HashMap到底差在哪**** 于是我一顿查资料.... 战犯哈希算法登场 哈希算法会根据你要存入的 ...

  9. Dubbo服务提供者如何优雅升级?

    文章首发于公众号:BiggerBoy.欢迎关注. 往期文章推荐 大坑!隐式转换导致索引失效...高性能分布式限流:Redis+Lua真香!MySQL索引知识点&常见问题汇总联合索引在B+树上的 ...

  10. Android Banner - ViewPager 02

    Android Banner - ViewPager 02 现在来给viewpager实现的banenr加上自动轮播 自动轮播的原理,使用handler的延迟消息来实现. 自动轮播实现如下内容 开始轮 ...