刘汝佳在书上说了状态转移方程, 嗯是三道题中较难的就动手写了一下。。
发现有的状态是无效的, 就去看了刘汝佳的代码, 额使用极大值来表示。。
这里也可以特殊判断(比如我) -----用IMPOSSIBLE表示不可能。
AC代码。
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#define maxn 10010
#define IMPOSSIBLE -12345
using namespace std;
int head[maxn], skip[2*maxn], V[2*maxn], mem;
vector<int> sons[maxn], DFSquen;
//int p[maxn];
void dfs(int u, int fa) {
DFSquen.push_back(u); //p[u] = fa;
for(int i = head[u]; i != -1; i = skip[i]) {
if(V[i] == fa) continue;
sons[u].push_back(V[i]);
dfs(V[i], u);
}
}
int d[maxn][3], pos;
int Get_answer() {
return d[0][2] == IMPOSSIBLE ?
d[0][0] : min(d[0][0],d[0][2]) ;
}
int main() {
int n;
while(scanf("%d",&n) == 1) {
mem = 0; int x,y; memset(head,-1,sizeof(head)) ;
for(int i = 1; i < n; i++) {
scanf("%d%d",&x,&y);
x--; y--;
V[mem] = y; skip[mem] = head[x]; head[x] = mem++;
V[mem] = x; skip[mem] = head[y]; head[y] = mem++;
}
for(int i = 0; i < n+1; i++) sons[i].clear();
DFSquen.clear();
dfs(0,-1);
for(int loop = DFSquen.size()-1; loop >=0; loop--) {
int j = DFSquen[loop];
if(sons[j].empty()) {
d[j][0] = 1; d[j][1] = 0; d[j][2] = IMPOSSIBLE;
}else {
int cnt = 0, k = sons[j].size(), lin;
d[j][0] = 1;
for(int o = 0; o < k; o++ ) {// if it is server
lin = sons[j][o];
if(d[lin][1] == IMPOSSIBLE)
d[j][0]+=d[lin][0];
else d[j][0] += min(d[lin][0],d[lin][1]);
}
d[j][1] = 0;
for(int o = 0; o < k; o++) { // if it isn't server but its father is server
lin = sons[j][o];
if(d[lin][2] == IMPOSSIBLE) {
cnt++; pos = lin;
} else d[j][1]+=d[lin][2];
}
if(cnt > 1) d[j][2] = IMPOSSIBLE;
else if(cnt == 1) d[j][2] = d[j][1] + d[pos][0];
else {
d[j][2] = 1000000000;
for(int o = 0; o < k; o++) {
lin = sons[j][o];
d[j][2] = min(d[j][2], d[j][1] - d[lin][2] + d[lin][0]);
}
}
if(cnt) d[j][1] = IMPOSSIBLE;
}
}
scanf("%d",&n);
printf("%d\n",Get_answer());
}
}