-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProblem_0928_minMalwareSpread.cc
147 lines (134 loc) · 3.22 KB
/
Problem_0928_minMalwareSpread.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <algorithm>
#include <numeric>
#include <vector>
#include "UnitTest.h"
using namespace std;
// TODO: figure it out.
// @sa https://www.bilibili.com/video/BV1Ny4y1F71J Code04
class Solution
{
private:
// [3,6,103]
// virus[3] = true;
// virus[103] = true;
// 方便查询
vector<bool> virus;
// 每个源头点删掉的话,能拯救多少点的数据
vector<int> cnts;
// 集合的标签 : 集合的感染点是什么点
// a : 代表点,整个集合源头是 infect[a]
// infect[a] == -1,目前这个集合没有发现源头
// infect[a] >= 0,目前这个集合源头是 infect[a]
// infect[a] == -2,目前这个集合源头不止一个,已经无法拯救了!
vector<int> infect;
// 并查集固有信息
vector<int> father;
// 集合的标签 : 集合的大小是多少
vector<int> size;
// 集合一定只放普通点,源头点根本不参与集合,也不是元素!
void build(int n, vector<int>& initial)
{
virus.resize(n, false);
cnts.resize(n, 0);
infect.resize(n, -1);
size.resize(n, 1);
father.resize(n);
std::iota(father.begin(), father.end(), 0);
for (auto& i : initial)
{
virus[i] = true;
}
}
int find(int i)
{
if (i != father[i])
{
father[i] = find(father[i]);
}
return father[i];
}
void unions(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
{
father[fx] = fy;
size[fy] += size[fx];
}
}
public:
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial)
{
int n = graph.size();
build(n, initial);
// 不是病毒的点,普通点合并!
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (graph[i][j] == 1 && !virus[i] && !virus[j])
{
unions(i, j);
}
}
}
// 病毒周围的普通点(集合 )去设置源头!
for (int sick : initial)
{
for (int neighbor = 0; neighbor < n; neighbor++)
{
if (sick != neighbor && !virus[neighbor] && graph[sick][neighbor] == 1)
{
int fn = find(neighbor);
if (infect[fn] == -1)
{
infect[fn] = sick;
}
else if (infect[fn] != -2 && infect[fn] != sick)
{
infect[fn] = -2;
}
}
}
}
// 统计拯救数据
for (int i = 0; i < n; i++)
{
// 不是代表点,不看
if (i == find(i) && infect[i] >= 0)
{
cnts[infect[i]] += size[i];
}
}
std::sort(initial.begin(), initial.end());
int ans = initial[0];
int max = cnts[ans];
for (int i : initial)
{
if (cnts[i] > max)
{
ans = i;
max = cnts[i];
}
}
return ans;
}
};
void test()
{
Solution s;
vector<vector<int>> g1 = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}};
vector<int> ini = {0, 1};
vector<vector<int>> g2 = {{1, 1, 0}, {1, 1, 1}, {0, 1, 1}};
vector<vector<int>> g3 = {{1, 1, 0, 0}, {1, 1, 1, 0}, {0, 1, 1, 1}, {0, 0, 1, 1}};
EXPECT_EQ_INT(0, s.minMalwareSpread(g1, ini));
EXPECT_EQ_INT(1, s.minMalwareSpread(g2, ini));
EXPECT_EQ_INT(1, s.minMalwareSpread(g3, ini));
EXPECT_SUMMARY;
}
int main()
{
test();
return 0;
}