[BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)
1.树形DP
#include <cstdio> #include <cstring> #include <iostream> #define N 10001 using namespace std; int n, cnt; int f[N][3], head[N], to[N << 1], next[N << 1]; bool vis[N]; //f[i][0]表示当前子树全选中,且根节点有放 //f[i][1]表示当前子树全选中,但根节点没放 //f[i][2]表示除了根节点以外,子树全选中 inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline void add(int x, int y) { to[cnt] = y; next[cnt] = head[x]; head[x] = cnt++; } inline void dfs(int u, int fa) { int i, v, flag = 0, falg = 0, tmp = 23333333; f[u][0] = vis[u] = 1; for(i = head[u]; ~i; i = next[i]) { v = to[i]; if(!vis[v]) { dfs(v, u); flag = 1; f[u][0] += min(f[v][0], min(f[v][1], f[v][2])); if(f[v][0] <= f[v][1]) { f[u][1] += f[v][0]; falg = 1; } else f[u][1] += f[v][1]; f[u][2] += f[v][1]; } } if(!falg) { for(i = head[u]; i ^ -1; i = next[i]) { v = to[i]; if(v != fa) tmp = min(tmp, f[u][1] - f[v][1] + f[v][0]); } f[u][1] = tmp; } if(!flag) f[u][1] = 23333333; } int main() { int i, x, y; n = read(); memset(head, -1, sizeof(head)); for(i = 1; i < n; i++) { x = read(); y = read(); add(x, y); add(y, x); } dfs(1, 0); printf("%d\n", min(f[1][0], f[1][1])); return 0; }
2.贪心
如果一个点的孩子节点或父亲节点有放,那么这个点就不用放了,如果这个点的儿子节点都没放,并且这个点和父亲节点也没放,那么就放在父节点上,ans++
#include <cstdio> #include <cstring> #include <iostream> #define N 10001 using namespace std; int n, cnt, ans; int head[N], to[N << 1], next[N << 1]; bool vis[N], f[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline void add(int x, int y) { to[cnt] = y; next[cnt] = head[x]; head[x] = cnt++; } inline void dfs(int u, int fa) { int i, v, flag = 0; //flag判断是否有儿子被覆盖 vis[u] = 1; for(i = head[u]; ~i; i = next[i]) { v = to[i]; if(!vis[v]) { dfs(v, u); if(f[v]) flag = 1; } } if(!flag && !f[u] && !f[fa]) f[fa] = 1, ans++; } int main() { int i, x, y; n = read(); memset(head, -1, sizeof(head)); for(i = 1; i < n; i++) { x = read(); y = read(); add(x, y); add(y, x); } dfs(1, 0); printf("%d\n", ans); return 0; }