Skip to content

Latest commit

 

History

History
342 lines (284 loc) · 8.13 KB

File metadata and controls

342 lines (284 loc) · 8.13 KB

English Version

题目描述

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

一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。

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

我们可以从初始列表中删除一个节点。如果移除这一节点将最小化 M(initial), 则返回该节点。如果有多个节点满足条件,就返回索引最小的节点。

请注意,如果某个节点已从受感染节点的列表 initial 中删除,它以后可能仍然因恶意软件传播而受到感染。

 

示例 1:

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

示例 2:

输入:graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]
输出:0

示例 3:

输入:graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]
输出:1

 

提示:

  • 1 < graph.length = graph[0].length <= 300
  • 0 <= graph[i][j] == graph[j][i] <= 1
  • graph[i][i] == 1
  • 1 <= initial.length < graph.length
  • 0 <= initial[i] < graph.length

解法

并查集。

模板 1——朴素并查集:

# 初始化,p存储每个点的父节点
p = list(range(n))

# 返回x的祖宗节点
def find(x):
    if p[x] != x:
        # 路径压缩
        p[x] = find(p[x])
    return p[x]

# 合并a和b所在的两个集合
p[find(a)] = find(b)

模板 2——维护 size 的并查集:

# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
p = list(range(n))
size = [1] * n

# 返回x的祖宗节点
def find(x):
    if p[x] != x:
        # 路径压缩
        p[x] = find(p[x])
    return p[x]

# 合并a和b所在的两个集合
if find(a) != find(b):
	size[find(b)] += size[find(a)]
	p[find(a)] = find(b)

模板 3——维护到祖宗节点距离的并查集:

# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
p = list(range(n))
d = [0] * n

# 返回x的祖宗节点
def find(x):
    if p[x] != x:
        t = find(p[x])
        d[x] += d[p[x]]
        p[x] = t
    return p[x]

# 合并a和b所在的两个集合
p[find(a)] = find(b)
d[find(a)] = distance

Python3

class Solution:
    def minMalwareSpread(self, graph: List[List[int]], initial: List[int]) -> int:
        n = len(graph)
        p = list(range(n))
        size = [1] * n

        def find(x):
            if p[x] != x:
                p[x] = find(p[x])
            return p[x]

        for i in range(n):
            for j in range(i + 1, n):
                if graph[i][j] == 1:
                    pa, pb = find(i), find(j)
                    if pa == pb:
                        continue
                    p[pa] = pb
                    size[pb] += size[pa]

        mi = float('inf')
        res = initial[0]
        initial.sort()
        for i in range(len(initial)):
            t = 0
            s = set()
            for j in range(len(initial)):
                if i == j:
                    continue
                if find(initial[j]) in s:
                    continue
                s.add(find(initial[j]))
                t += size[find(initial[j])]
            if mi > t:
                mi = t
                res = initial[i]
        return res

Java

class Solution {
    private int[] p;

    public int minMalwareSpread(int[][] graph, int[] initial) {
        int n = graph.length;
        p = new int[n];
        for (int i = 0; i < n; ++i) {
            p[i] = i;
        }
        int[] size = new int[n];
        Arrays.fill(size, 1);
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (graph[i][j] == 1) {
                    int pa = find(i), pb = find(j);
                    if (pa == pb) {
                        continue;
                    }
                    p[pa] = pb;
                    size[pb] += size[pa];
                }
            }
        }
        int mi = Integer.MAX_VALUE;
        int res = initial[0];
        Arrays.sort(initial);
        for (int i = 0; i < initial.length; ++i) {
            int t = 0;
            Set<Integer> s = new HashSet<>();
            for (int j = 0; j < initial.length; ++j) {
                if (i == j) {
                    continue;
                }
                if (s.contains(find(initial[j]))) {
                    continue;
                }
                s.add(find(initial[j]));
                t += size[find(initial[j])];
            }
            if (mi > t) {
                mi = t;
                res = initial[i];
            }
        }
        return res;
    }

    private int find(int x) {
        if (p[x] != x) {
            p[x] = find(p[x]);
        }
        return p[x];
    }
}

C++

class Solution {
public:
    vector<int> p;

    int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n = graph.size();
        p.resize(n);
        for (int i = 0; i < n; ++i) p[i] = i;
        vector<int> size(n, 1);
        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j < n; ++j)
            {
                if (graph[i][j])
                {
                    int pa = find(i), pb = find(j);
                    if (pa == pb) continue;
                    p[pa] = pb;
                    size[pb] += size[pa];
                }
            }
        }
        int mi = 400;
        int res = initial[0];
        sort(initial.begin(), initial.end());
        for (int i = 0; i < initial.size(); ++i)
        {
            int t = 0;
            unordered_set<int> s;
            for (int j = 0; j < initial.size(); ++j)
            {
                if (i == j) continue;
                if (s.count(find(initial[j]))) continue;
                s.insert(find(initial[j]));
                t += size[find(initial[j])];
            }
            if (mi > t)
            {
                mi = t;
                res = initial[i];
            }
        }
        return res;
    }

    int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
};

Go

var p []int

func minMalwareSpread(graph [][]int, initial []int) int {
	n := len(graph)
	p = make([]int, n)
	size := make([]int, n)
	for i := 0; i < n; i++ {
		p[i] = i
		size[i] = 1
	}
	for i := 0; i < n; i++ {
		for j := i + 1; j < n; j++ {
			if graph[i][j] == 1 {
				pa, pb := find(i), find(j)
				if pa == pb {
					continue
				}
				p[pa] = pb
				size[pb] += size[pa]
			}
		}
	}
	mi := 400
	res := initial[0]
	sort.Ints(initial)
	for i := 0; i < len(initial); i++ {
		t := 0
		s := make(map[int]bool)
		for j := 0; j < len(initial); j++ {
			if i == j {
				continue
			}
			if s[find(initial[j])] {
				continue
			}
			s[find(initial[j])] = true
			t += size[find(initial[j])]
		}
		if mi > t {
			mi = t
			res = initial[i]
		}
	}
	return res
}

func find(x int) int {
	if p[x] != x {
		p[x] = find(p[x])
	}
	return p[x]
}

...