题目链接:http://arena.acmclub.com/problem.php?id=15595
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
static int max = 200 + 10;
static int[][] d = new int[max][2];// d[i][0]表示不选,d[i][1]表示选。
// f[i][0]==1表示不选,且方案唯一,f[i][0]==0表示选、且方案不唯一。
// f[i][1]==1表示选,且方案唯一,f[i][1]==0表示选、且方案不唯一。
static int[][] f = new int[max][2];
static ArrayList<Integer>[] sons = new ArrayList[max];
static Map<String, Integer> dict;
static int n;
static int cnt;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
n = in.nextInt();
if (n == 0)
break;
cnt = 0;
dict = new HashMap<String, Integer>();
for (int i = 0; i < n; i++) {
sons[i] = new ArrayList<Integer>();
}
String s = in.next();
ID(s);
for (int i = 0; i < n - 1; i++) {
String s1 = in.next();// 下属
String s2 = in.next();// 上司
sons[ID(s2)].add(ID(s1));
}
int max0 = dp(0, 0);
int max1 = dp(0, 1);
System.out.print(Math.max(max0, max1) + " ");
boolean unique = false;
if (max1 > max0 && f[0][1] == 1)
unique = true;
if (max0 > max1 && f[0][0] == 1)//注意这里不是else if。
unique = true;
if (unique)
System.out.println("Yes");
else
System.out.println("No");
}
}
public static int ID(String s) {//这里运用与uva12186类似的方法
if (dict.get(s) == null)//将上司(编号)的下属(编号)添加到上司所在的容器中。
dict.put(s, cnt++);
return dict.get(s);
}
public static int dp(int u, int k) {
f[u][k] = 1;// 先默认设置为1,然后在后面的判断中,不满足条件,再改为0
d[u][k] = k;// 选中为0,不选中为1,而0和1都是k值,故d[u][k] = k;
for (int i = 0; i < sons[u].size(); i++) {
int v = sons[u].get(i);// 上司u的下属v。
if (k == 1) {
d[u][1] += dp(v, 0);
if (f[v][0] == 0)
f[u][1] = 0;
} else {
int max0 = dp(v, 0);
int max1 = dp(v, 1);
d[u][0] += Math.max(max0, max1);
if (max0 > max1 && f[v][0] == 0)
f[u][0] = 0;
else if (max1 > max0 && f[v][1] == 0)
f[u][0] = 0;
else if (max0 == max1)
f[u][0] = 0;
}
}
return d[u][k];
}
}
题意:
一个公司员工要举行聚会,公司里有n(n<=200)个人形成一个树状结构。要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一
分析:
本题几乎就是树的最大独立集问题,不过多了一个要求:判断唯一性。设:
1,d(u,0)和f(u,0)表示以u为根的子树中,不选uhko 能得到的最大人数以及方案唯一性。(f(u,0)=1表示唯一,0表示不唯一)
2,d(u,1)和f(u,1)表示以u为根的子树中,选u点能得到的最大人数以及方案的唯一性。
相应地,状态转移方程也有两套。
1,d(u,1)的计算:因为选了u,所以u的子结点都不能选,因此d(u,1)=sum{d(v,0) | v是u的子结点}。当且仅当所有f(v,0)=1时,f(u,1)才是1。
2,d(u,0)的计算:因为u没有选,所以每个子结点v可选可不选,即d(u,0) = sum{max (d(v,0),d(v,1))}。什么情况下方案是唯一的呢?首先,如果某个d(v,0)和d(v,1)相等,则不唯一;其次,如果max取到的那个值对应的f=0,方案也不唯一(如d(v,0)>d(v,1) && f(v,0)==0,则f(u,0)=0;这里可以细分为两种情况)。