E. Sasha and the Happy Tree Cutting:
题目大意:
思路解析:
现在有一颗树,然后给出了k对路径,然后要求路径上至少有一个结点是被染色了的,如果这k对路径没有共用边,那我们至少需要染色k条边。如果有共用边,那么选择将他染色,那么就可以使多个路径满足条件。现在求最小是染色树。已知最多需要20条边,那我们可以找出哪些边可以进行染色(并且它染色后能解决哪些路径),然后进行状压dp。
代码实现:
import java.util.*;import java.io.*;
import java.math.*;public class Main {static int[] pre;static Vector<int[]>[] g;public static void main(String[] args) throws IOException {int t = f.nextInt();while (t > 0) {solve();t--;}w.flush();w.close();}public static void solve() throws IOException{int n = f.nextInt();g = new Vector[n+1];pre = new int[n+1];for (int i = 0; i < n + 1; i++) {g[i] = new Vector<>();}for (int i = 0; i < n - 1; i++) {int x = f.nextInt();int y = f.nextInt();g[x].add(new int[] {y, i});g[y].add(new int[] {x, i});}int[] st = new int[n];dfs1(1, 0);int k = f.nextInt();for (int i = 0; i < k; i++) {int x = f.nextInt(); int y = f.nextInt();if (pre[x] != 0) dfs2(x);while ((x ^ y) != 0){for (int j = 0; j < g[y].size(); j++) {int[] cur = g[y].get(j);if (cur[0] == pre[y]){y = pre[y];st[cur[1]] |= (1 << i);break;}}}}HashSet<Integer> set = new HashSet<>();for (int i = 0; i < n; i++) {if (st[i] > 0)set.add(st[i]);}int[] dp = new int[1 << k];Arrays.fill(dp, 1000);dp[0] = 0;for (int i = 0; i < (1 << k); i++) {for (Integer j: set){dp[i | j] = Math.min(dp[i|j], dp[i] + 1);}}w.println(dp[(1 << k) - 1]);}public static void dfs1(int x, int fa){for (int i = 0; i < g[x].size(); i++) {int[] cur = g[x].get(i);int y = cur[0];if (y == fa) continue;pre[y] = x;dfs1(y, x);}}public static void dfs2(int x){int y = pre[x];pre[x] = 0;while (y != 0){int t = pre[y];pre[y] = x;x = y;y = t;}}static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));static Input f = new Input(System.in);static class Input {public BufferedReader reader;public StringTokenizer tokenizer;public Input(InputStream stream) {reader = new BufferedReader(new InputStreamReader(stream), 32768);tokenizer = null;}public String next() throws IOException{while (tokenizer == null || !tokenizer.hasMoreTokens()) {tokenizer = new StringTokenizer(reader.readLine());}return tokenizer.nextToken();}public int nextInt() throws IOException {return Integer.parseInt(next());}public long nextLong() throws IOException {return Long.parseLong(next());}public Double nextDouble() throws IOException {return Double.parseDouble(next());}}
}