2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示

在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j。

一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,

且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。

这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。

假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。

我们可以从 initial 中删除一个节点,

并完全移除该节点以及从该节点到任何其他节点的任何连接。

请返回移除后能够使 M(initial) 最小化的节点。

如果有多个节点满足条件,返回索引 最小的节点 。

initial 中每个整数都不同。

输出:graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]。

输入:0。

答案2023-06-10:

主要思路如下:

1.建立并查集,将感染恶意软件的节点标记出来。

2.遍历节点连接,如果两个节点都没有被感染,则在并查集中合并这两个节点。

3.对于initial中的每个节点,遍历其能够直接连接的节点,如果节点未被感染,则将其在并查集中的祖先标记为initial中的该节点,如果该祖先已被标记为其他initial中的节点,则将其标记为-2。

4.统计在同一个initial的所有节点中,连接的总节点数,找出连接数最多的initial节点。

5.返回最小索引的节点。

时间复杂度为$O(n2)$,其中n是节点数,因为要对每个节点进行遍历和合并操作,最坏情况下需要$O(n2)$次遍历和合并操作。

空间复杂度为O(n),其中n是节点数,因为需要使用一个并查集数组来存储节点的父节点,另外还需要使用一个数组来记录每个节点是否被感染和每个initial节点的连接数量。这些数据占用的空间都是O(n)的。

go完整代码如下:

package main

import (
"fmt"
"sort"
) func minMalwareSpread(graph [][]int, initial []int) int {
n := len(graph)
virus := make([]bool, n)
for _, i := range initial {
virus[i] = true
} uf := NewUnionFind(n)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
if graph[i][j] == 1 && !virus[i] && !virus[j] {
uf.Union(i, j)
}
}
} infect := make([]int, n)
for i := range infect {
infect[i] = -1
}
for _, v := range initial {
for next := 0; next < n; next++ {
if v != next && !virus[next] && graph[v][next] == 1 {
f := uf.Find(next)
if infect[f] == -1 {
infect[f] = v
} else if infect[f] != -2 && infect[f] != v {
infect[f] = -2
}
}
}
} cnt := make([]int, n)
for i := 0; i < n; i++ {
if infect[i] >= 0 {
cnt[infect[i]] += uf.size[i]
}
} sort.Ints(initial)
ans := initial[0]
count := cnt[ans]
for _, i := range initial {
if cnt[i] > count {
ans = i
count = cnt[i]
}
} return ans
} type UnionFind struct {
father []int
size []int
} func NewUnionFind(n int) *UnionFind {
father := make([]int, n)
size := make([]int, n)
for i := 0; i < n; i++ {
father[i] = i
size[i] = 1
}
return &UnionFind{father, size}
} func (uf *UnionFind) Find(i int) int {
help := make([]int, 0)
for i != uf.father[i] {
help = append(help, i)
i = uf.father[i]
}
for _, v := range help {
uf.father[v] = i
}
return i
} func (uf *UnionFind) Union(i, j int) {
fi, fj := uf.Find(i), uf.Find(j)
if fi != fj {
if uf.size[fi] >= uf.size[fj] {
uf.father[fj] = fi
uf.size[fi] += uf.size[fj]
} else {
uf.father[fi] = fj
uf.size[fj] += uf.size[fi]
}
}
} func main() {
graph := [][]int{{1, 1, 0}, {1, 1, 0}, {0, 0, 1}}
initial := []int{0, 1} fmt.Println(minMalwareSpread(graph, initial))
}

rust完整代码如下:

fn main() {
let graph = vec![vec![1, 1, 0], vec![1, 1, 0], vec![0, 0, 1]];
let initial = vec![0, 1]; println!("{}", min_malware_spread(graph, initial));
} struct UnionFind {
father: Vec<i32>,
size: Vec<i32>,
help: Vec<i32>,
} impl UnionFind {
fn new(n: usize) -> Self {
let mut father = vec![0; n];
let mut size = vec![0; n];
let mut help = vec![0; n];
for i in 0..n {
father[i] = i as i32;
size[i] = 1;
}
Self { father, size, help }
} fn find(&mut self, mut i: i32) -> i32 {
let mut hi = 0;
while i != self.father[i as usize] {
self.help[hi as usize] = i;
hi += 1;
i = self.father[i as usize];
}
while hi != 0 {
hi -= 1;
self.father[self.help[hi as usize] as usize] = i;
}
i
} fn union(&mut self, i: i32, j: i32) {
let fi = self.find(i);
let fj = self.find(j);
if fi != fj {
if self.size[fi as usize] >= self.size[fj as usize] {
self.father[fj as usize] = fi;
self.size[fi as usize] += self.size[fj as usize];
} else {
self.father[fi as usize] = fj;
self.size[fj as usize] += self.size[fi as usize];
}
}
}
} fn min_malware_spread(graph: Vec<Vec<i32>>, initial: Vec<i32>) -> i32 {
let mut graph = graph;
let mut initial = initial;
let n: usize = graph.len();
let mut virus = vec![false; n];
for i in initial.iter() {
virus[*i as usize] = true;
} let mut uf = UnionFind::new(n);
for i in 0..n {
for j in 0..n {
if graph[i][j] == 1 && !virus[i] && !virus[j] {
uf.union(i as i32, j as i32);
}
}
} let mut infect = vec![-1; n];
for &v in initial.iter() {
for next in 0..n {
if v != next as i32 && !virus[next] && graph[v as usize][next as usize] == 1 {
let f = uf.find(next as i32);
if infect[f as usize] == -1 {
infect[f as usize] = v;
} else if infect[f as usize] != -2 && infect[f as usize] != v {
infect[f as usize] = -2;
}
}
}
} let mut cnt = vec![0; n];
for i in 0..n {
if infect[i] >= 0 {
cnt[infect[i] as usize] += uf.size[i as usize];
}
} initial.sort();
let mut ans = initial[0];
let mut count = cnt[ans as usize];
for &i in initial.iter() {
if cnt[i as usize] > count {
ans = i;
count = cnt[i as usize];
}
} ans
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; class UnionFind {
public:
vector<int> father;
vector<int> size; // Constructor
UnionFind(int n) {
father.resize(n);
size.resize(n);
for (int i = 0; i < n; i++) {
father[i] = i;
size[i] = 1;
}
} // Find operation
int Find(int i) {
vector<int> help;
while (i != father[i]) {
help.push_back(i);
i = father[i];
}
for (auto v : help) {
father[v] = i;
}
return i;
} // Union operation
void Union(int i, int j) {
int fi = Find(i);
int fj = Find(j);
if (fi != fj) {
if (size[fi] >= size[fj]) {
father[fj] = fi;
size[fi] += size[fj];
}
else {
father[fi] = fj;
size[fj] += size[fi];
}
}
}
}; int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
int n = graph.size(); vector<bool> virus(n, false);
for (auto i : initial) {
virus[i] = true;
} UnionFind uf(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (graph[i][j] == 1 && !virus[i] && !virus[j]) {
uf.Union(i, j);
}
}
} vector<int> infect(n, -1);
for (auto v : initial) {
for (int next = 0; next < n; next++) {
if (v != next && !virus[next] && graph[v][next] == 1) {
int f = uf.Find(next);
if (infect[f] == -1) {
infect[f] = v;
}
else if (infect[f] != -2 && infect[f] != v) {
infect[f] = -2;
}
}
}
} vector<int> cnt(n, 0);
for (int i = 0; i < n; i++) {
if (infect[i] >= 0) {
cnt[infect[i]] += uf.size[i];
}
} sort(initial.begin(), initial.end());
int ans = initial[0];
int count = cnt[ans];
for (auto i : initial) {
if (cnt[i] > count) {
ans = i;
count = cnt[i];
}
} return ans;
} int main() {
vector<vector<int>> graph = { {1, 1, 0}, {1, 1, 0}, {0, 0, 1} };
vector<int> initial = { 0, 1 }; cout << minMalwareSpread(graph, initial) << endl; return 0;
}

c完整代码如下:

#include <stdio.h>
#include <stdlib.h> int cmpfunc(const void* a, const void* b); typedef struct {
int* father;
int* size;
} UnionFind; UnionFind* createUnionFind(int n) {
UnionFind* uf = (UnionFind*)malloc(sizeof(UnionFind));
uf->father = (int*)malloc(n * sizeof(int));
uf->size = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
uf->father[i] = i;
uf->size[i] = 1;
}
return uf;
} int find(UnionFind* uf, int i) {
int hi = 0;
int* help = (int*)malloc(1000 * sizeof(int));
while (i != uf->father[i]) {
help[hi] = i;
hi += 1;
i = uf->father[i];
}
for (int j = 0; j < hi; j++) {
uf->father[help[j]] = i;
}
free(help);
return i;
} void unionSet(UnionFind* uf, int i, int j) {
int fi = find(uf, i);
int fj = find(uf, j);
if (fi != fj) {
if (uf->size[fi] >= uf->size[fj]) {
uf->father[fj] = fi;
uf->size[fi] += uf->size[fj];
}
else {
uf->father[fi] = fj;
uf->size[fj] += uf->size[fi];
}
}
} int minMalwareSpread(int** graph, int graphSize, int* graphColSize, int* initial, int initialSize) {
int n = graphSize; int* virus = (int*)calloc(n, sizeof(int));
for (int i = 0; i < initialSize; i++) {
virus[initial[i]] = 1;
} UnionFind* uf = createUnionFind(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (graph[i][j] == 1 && virus[i] == 0 && virus[j] == 0) {
unionSet(uf, i, j);
}
}
} int* infect = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
infect[i] = -1;
}
for (int k = 0; k < initialSize; k++) {
int v = initial[k];
for (int next = 0; next < n; next++) {
if (v != next && virus[next] == 0 && graph[v][next] == 1) {
int f = find(uf, next);
if (infect[f] == -1) {
infect[f] = v;
}
else if (infect[f] != -2 && infect[f] != v) {
infect[f] = -2;
}
}
}
} int* cnt = (int*)calloc(n, sizeof(int));
for (int i = 0; i < n; i++) {
if (infect[i] >= 0) {
cnt[infect[i]] += uf->size[i];
}
} int* sortedInitial = (int*)malloc(initialSize * sizeof(int));
for (int i = 0; i < initialSize; i++) {
sortedInitial[i] = initial[i];
}
qsort(sortedInitial, initialSize, sizeof(int), cmpfunc); int ans = sortedInitial[0];
int count = cnt[ans];
for (int i = 0; i < initialSize; i++) {
if (cnt[sortedInitial[i]] > count) {
ans = sortedInitial[i];
count = cnt[ans];
}
} free(virus);
free(cnt);
free(sortedInitial);
free(infect);
free(uf->father);
free(uf->size);
free(uf); return ans;
} int cmpfunc(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
} int main() {
int graphSize = 3;
int graphColSize[] = { 3, 3, 3 };
int graphData[][3] = { {1, 1, 0}, {1, 1, 0}, {0, 0, 1} };
int** graph = (int**)malloc(graphSize * sizeof(int*));
for (int i = 0; i < graphSize; i++) {
graph[i] = (int*)malloc(graphColSize[i] * sizeof(int));
for (int j = 0; j < graphColSize[i]; j++) {
graph[i][j] = graphData[i][j];
}
} int initial[] = { 0, 1 };
int initialSize = 2;
int ans = minMalwareSpread(graph, graphSize, graphColSize, initial, initialSize);
printf("%d\n", ans); for (int i = 0; i < graphSize; i++) {
free(graph[i]);
}
free(graph); return 0;
}

2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j。的更多相关文章

  1. AJAX请求 $.ajaxSetup方法的使用:设置AJAX请求的默认参数选项,当程序中需要发起多个AJAX请求时,则不用再为每一个请求配置请求的参数

    定义和用法ajaxSetup() 方法为将来的 AJAX 请求设置默认值.语法$.ajaxSetup({name:value, name:value, ... }) 该参数为带有一个或多个名称/值对的 ...

  2. CF F - Tree with Maximum Cost (树形DP)给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大。输出最大的值。

    题目意思: 给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大.输出最大的值. ...

  3. 如何在WTL和MFC中使用duilib及如何静态使用duilib库!(初级讲解 附带一个Demo)

    关于duilib的历史,我也就不多说了,能看到这篇文章的人都是有一定了解才能找到这个的. 我直接说下对这个库的基本使用吧. 我个人对一些好技术都是比较感兴趣的. 因为个人原因 喜欢接触一个好技术. 所 ...

  4. 功能要求:定义一个两行三列的二维数组 names 并赋值,使用二重循环输出二维数组中的元素。

    功能要求:定义一个两行三列的二维数组 names 并赋值,使用二重循环输出二维数组中的元素 names={{"tom","jack","mike&qu ...

  5. 设置一个div网页滚动时,使其固定在头部,当页面滚动到距离头部300px时,隐藏该div,另一个div在底部,此时显示;当页面滚动到起始位置时,头部div出现,底部div隐藏

    设置一个div网页滚动时,使其固定在头部,当页面滚动到距离头部300px时,隐藏该div,另一个div在底部,此时显示: 当页面滚动到起始位置时,头部div出现,底部div隐藏 前端代码: <! ...

  6. 在Hive中执行DDL之类的SQL语句时遇到的一个问题

    在Hive中执行DDL之类的SQL语句时遇到的一个问题 作者:天齐 遇到的问题如下: hive> create table ehr_base(id string); FAILED: Execut ...

  7. SpringMVC 中,当前台传入多个参数时,可将参数封装成一个bean类

    在实际业务场景中,当前台通过 url 向后台传送多个参数时,可以将参数封装成一个bean类,在bean类中对各个参数进行非空,默认值等的设置. 前台 url ,想后台传送两个参数,userName 和 ...

  8. 问题-[Delphi]在对GRID设置单击为编辑时,其他GRID可以,但有一个GRID不行?

    问题现象:在对GRID设置单击为编辑时,其他GRID可以,但有一个GRID不行?问题原因:在这个GRID中的单击事件可能不存在,可以测试一下有没有单击事件.解决方法:需要在GRID的上一个类中,放开单 ...

  9. 安装Office时出现windows installer服务不能更新一个或多个受保护的windows文件错误的解决方法

    今天在Windows XP上安装Microsoft Office 2010时,总是遇到“Windows Installer服务不能更新一个或多个受保护的windows文件,安装失败,正在回滚更改”提示 ...

  10. 【中英对照】【EntLib6】【Unity】实验1:使用一个Unity容器

    Lab 1: Using a Unity Container 实验1:使用一个Unity容器 Estimated time to complete this lab: 15 minutes 估计完成时 ...

随机推荐

  1. Ubuntu+uWSGI部署基于Django的API【鸿篇巨制,事无巨细】

    背景 任务: 视频翻译项目需要在两个服务器上进行通信(国内&海外的阿里服务器). 因为python是主语言,选用了Django 来快速部署API. 注:Django中文文档:https://d ...

  2. selenium验证码处理-获取验证码图片二进流数据转成原图保存

    1.因为视频的作者给的代码不完整,只有核心部分的代码. 2.视频作者示例使用的第三方破解12306的脚本网页(失效了) 所以本人无法复现,此次截取部分代码作为理解核心意思(思想方法最重要) 1.面向对 ...

  3. 景顺长城基于 Apache APISIX 在金融云原生的生产实践

    本文介绍了景顺长城在金融云原生架构演进中选择 APISIX 作为网关工具的技术细节,同时分享了使用 APISIX 的实践细节,并对 APISIX 的未来展望进行了探讨. 作者李奕浩,景顺长城信息技术部 ...

  4. 迁移学习(COAL)《Generalized Domain Adaptation with Covariate and Label Shift CO-ALignment》

    论文信息 论文标题:Generalized Domain Adaptation with Covariate and Label Shift CO-ALignment论文作者:Shuhan Tan, ...

  5. pinia的使用

    1. pinia和vuex的区别 pinia没有mutations,只有:state. getters. actions pinia分模块不需要modules(之前vuex分模块需要modules) ...

  6. 数据结构哈夫曼树(C语言版)

    文章目录 一. 问题 需求分析 代码分析 结构体定义使用 建立哈夫曼树,首先需要找到两个权值最小的两个叶子结点,然后建树 哈夫曼编码(我采用的是从叶子结点-->根节点,所以实际是反过来的) 使用 ...

  7. Java Lambda Stream

    ::方法使用 条件:lambada表达式的主体仅包含一个表达式,且lambada表达式只调用一个已经存在的方法:被引用的方法的参数列表与lambada表达式的输入输出一致 以下是Java 8中方法引用 ...

  8. [ZJOI2020] 序列 线性规划做法/贪心做法

    线性规划做法 同时也作为线性规划对偶的一个小小的学习笔记. 以下 \(\cdot\) 表示点积,\(b,c,x,y\) 是行向量. \(A\) 是矩阵,对于向量 \(u,v\) 若 \(\forall ...

  9. 网站七牛云CDN加速配置

    首先进入七牛云管理平台 1.添加域名 2.添加需要加速的域名,比如我添加的是gechuang.net 3.源站配置,这里要用IP地址,访问的目录下面要有能访问测试的文件 4.缓存配置,也就是配置缓存哪 ...

  10. 代码打包的可视化数据分析图: webpack-bundle-analyzer 的使用

    先看webpack-bundle-analyzer的效果图(官方效果图): 通过使用webpack-bundle-analyzer可以看到项目各模块的大小,可以按需优化 1.先安装 npm insta ...