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 }