恶意代码 - Malicious Code - BFS & 01背包
恶意代码
(测试用例总数:X 个,1 秒 (C/C++),1.5 秒 (JAVA)/内存要求:256 M,Stack 1 M)
S 公司的网络管理员琳收到了一通紧急来电。来电告知公司内部设备连接的网络中发现了恶意代码,必须马上采取相应措施。
S 公司有 N 台设备,通过 M 根线路连接,所以如果其中一台设备感染恶意代码,其他设备也会通过连接网络感染上恶意代码。目前,已有 K 台设备感染恶意代码,代码扩散危机迫在眉睫。受感染的设备需要立即处理,但在目前的情况下,最多只能处理三台设备。
保受感染的设备数量尽可能少的情况下,帮助琳确定要处理的设备,同时求出未受感染设备的最大数量。

如上图所示,有 10 台设备连接,编号为 2、4、5、8 的设备感染了恶意代码,处理编号为 2、4、5 的设备,就可以保护 7 台设备,这是能实现的不受感染设备的最大数量。
[限制条件]
1.设备数量N为5以上,100,000以下的整数。
2.线路数量 M 为1以上,300,000以下的整数。
3.受感染的设备数K为3以上,N以下的整数。
4.受感染的设备即使经过处理后,仍然可能会再次被其他受感染的设备感染。
[输入]
首先给出测试用例数量T,随后给出T个测试用例。在每个测试用例的第一行,给定设备数量 N,线路数量 M、感染恶意代码的设备数量 K,以空格分隔。从第二行到第M行,每行给定一条线路两端连接的设备 A 和 B 的编号,以空格分隔。在第 M+2 行,给定 K 台感染恶意代码的设备编号,以空格分隔。
[输出]
每行输出一个测试用例。首先,输出“#x”(其中 x 表示测试用例编号,从 1 开始),加一个空格,最后输出处理三台设备后,恶性代码扩散时,能实现的未感染设备的最大数量。
[输入和输出示例]
(输入)
2
10 9 4
1 2
2 3
2 5
4 5
4 6
5 6
5 7
8 9
9 10
2 4 5 8
10 9 5
1 2
2 3
2 5
4 5
4 6
5 6
5 7
8 9
9 10
2 4 5 6 8
(输出)
#1 7
#2 3
思路分析:
bfs遍历算出每个连通图中感染病毒的结点数及连通图总结点数,感染病毒结点数>3 则丢弃,<=3存放在List集合中
根据题意最多可修复的电脑数是3个,可以理解为01背包中已知最大容量,将感染的电脑看做一个整体的物品,物品权重wi即可修复的电脑数量,物品价值即连通图节点数
套用01背包工时dp[j] = max(dp[j-w[i]]+vi,dp[j]),最后算出的dp[3] 则为最后的结果
package graph;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
import java.util.StringTokenizer;
/**
* 恶意代码思路分析:
* bfs+01背包
* bfs遍历算出每个连通图中感染病毒的结点数及连通图总结点数,感染病毒结点数>3 则丢弃,<=3存放在List集合中
* 根据题意最多可修复的电脑数是3个,可以理解为01背包中已知最大容量,将感染的电脑看做一个整体的物品,物品权重wi即可修复的电脑数量,物品价值即连通图节点数
* 套用01背包工时dp[j] = max(dp[j-w[i]]+vi,dp[j]),最后算出的dp[3] 则为最后的结果
*
* @author XA-GDD
*
*/
public class EQ_MaliciousCode_0712 {
static int T,N,M,K;
static int _max_Nval = 100000;
static ArrayList<Integer> [] adjList = new ArrayList[_max_Nval+1];
static boolean [] badNode = new boolean[_max_Nval+1];
static boolean [] visited = new boolean[_max_Nval+1];
static ArrayList<int []> list = new ArrayList<int[]>();
static int [] dp = new int[4];
static int nodeCnt;
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("D:\\workspace\\sw_pro\\test_case\\sample_input_0712.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
T = Integer.parseInt(st.nextToken());
for(int testCase = 1; testCase<= T;testCase++) {
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
for(int i=1;i<=N;i++) {
adjList[i] = new ArrayList<Integer>();
}
// Arrays.fill(adjList, new ArrayList<Integer>()); 初始化不可用此代码
Arrays.fill(badNode, false);
Arrays.fill(visited, false);
list.clear();
Arrays.fill(dp, 0);
nodeCnt = 0;
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
adjList[s].add(e);
adjList[e].add(s);
}
st = new StringTokenizer(br.readLine());
for(int i=0;i<K;i++) {
int node = Integer.parseInt(st.nextToken());
badNode[node] = true;
}
for(int i=1;i<=N;i++) {
if(nodeCnt==N) {
break;
}
if(!visited[i]) {
bfs(i);
}
}
getResult();
System.out.printf("#%d %d\n",testCase,dp[3]);
}
}
//0-1背包
static void getResult() {
for(int i=0;i<list.size();i++) {
int wi = list.get(i)[1];
int vi = list.get(i)[0];
for(int j=3;j>=wi;j--) {
dp[j] = Math.max(dp[j], dp[j-wi]+vi);
}
}
}
//bfs遍历算出每个连通图中感染病毒的结点数及连通图总结点数,感染病毒结点数>3 则丢弃,<=3存放在List集合中
static void bfs(int s) {
Queue<Integer> queue = new ArrayDeque<Integer>();
queue.add(s);
visited[s] = true;
int nodeTotCnt = 0; //连通图的节点个数
int badNodeCnt = 0; //坏节点个数
while(!queue.isEmpty()) {
int curr = queue.poll();
nodeTotCnt++;
nodeCnt++;
if(badNode[curr]) {
badNodeCnt++;
}
for(int i=0;i<adjList[curr].size();i++) {
int next = adjList[curr].get(i);
if(!visited[next]) {
queue.add(next);
visited[next] = true;
}
}
}
if(badNodeCnt<=3) {
list.add(new int[] {nodeTotCnt,badNodeCnt});
}
}
}
浙公网安备 33010602011771号