点击题号跳转

A4789 B1123 C4266 D3672 E3412

F5360 G4871 H5331 I2291 J5610

A.传染病控制回到顶部

题意

给一棵树1为根被感染,每次切断一条边,然后从已经被感染的传播到相邻节点,若相连则被传染,问如何操作使得感人的人最少,n<=300

题解

考虑一个贪心做法,显然可以按照深度下来,求出每个点对应的深度,每次切对应深度的点儿子最多的树

显然这样并不能AC,考虑一种情况,一个节点一条链儿子最多,另一个节点分叉,那么如果切分叉,再来切链显然比贪心更优

那么就需要搜索所有的情况,显然按照贪心思路下来,获得的值较优,再来剪枝复杂度会大大降低,复杂度O(常数*n^2)

代码

 1 import java.util.*;
 2 
 3 public class Main {
 4 
 5     private Scanner sc;
 6 
 7     public static void main(String[] args) {
 8 
 9         Scanner sc = new Scanner(System.in);
10         Solution solver = new Solution();
11         solver.solve(sc);
12     }
13 
14 }
15 
16 class Solution {
17 
18     private int[][] G = new int[305][305];
19     private int[] sz = new int[305];
20     private int[] deep = new int[305];
21     private int[] father = new int[305];
22     private boolean[] vis = new boolean[305];
23     private int n, m, deaded;
24     public void solve(Scanner sc) {
25         n = sc.nextInt();
26         m = sc.nextInt();
27         for (int i = 0; i < m; i++) {
28             int u = sc.nextInt();
29             int v = sc.nextInt();
30             G[u][v] = G[v][u] = 1;
31         }
32         dfs(1, 1, 1);
33         deaded = n;
34         dep_dfs(1, 1);
35         System.out.println(deaded);
36     }
37 
38     private void dfs(int u, int fa, int dep) {
39         sz[u] = 1;
40         deep[u] = dep;
41         father[u] = fa;
42         for (int v = 1; v <= n; v++) {
43             if (G[u][v] == 1 && v != fa) {
44                 dfs(v, u, dep + 1);
45                 sz[u] += sz[v];
46             }
47         }
48     }
49 
50     private void dep_dfs(int dep, int dead) {
51         if (dead >= deaded) return;
52         //处理一层节点
53         for (int i = 2; i <= n; i++) {
54             if (deep[i] == dep + 1) {
55                 //System.out.println("i:" + i + " fa:" + father[i]);
56                 //System.out.println("vis[i]:" + vis[i] + " vis[fa]:" + vis[father[i]]);
57                 vis[i] = vis[father[i]];
58             }
59         }
60         //sum代表这一层有多少个会死掉的节点
61         int sum = 0;
62         for (int i = 2; i <= n; i++) {
63             if (deep[i] == dep + 1 && !vis[i]) {
64                 sum++;
65             }
66         }
67         //System.out.println("max:" + max);
68         //System.out.println("sum:" + sum);
69         //这一层所有的节点都活着,结束
70         if (sum == 0) {
71             //System.out.println("dead:" + dead);
72             deaded = Math.min(deaded, dead);
73             return;
74         }
75         //选择儿子最多的活下来
76         for (int i = 2; i <= n; i++) {
77             if (deep[i] == dep + 1 && !vis[i]) {
78                 //System.out.println("cut:" + i);
79                 vis[i] = true;
80                 dep_dfs(dep + 1, dead + sum - 1);
81                 vis[i] = false;
82             }
83         }
84     }
85 
86 }
A

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-01
  • 2021-12-24
  • 2021-09-16
  • 2021-05-07
  • 2021-06-12
  • 2021-06-18
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案