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());
}
}
}