HDU6178 Monkeys
题意:一棵树有n个点,要求在其中的k个点上面放猴子,每一个猴子要与其他猴子中的一只相连,问要保留几条边
题解:分析可得,每一只猴子要和其他猴子相连,有两种情况,第一种是直接配对相连,第二种是单个连到已经配对好的,可以先算出最大匹配数,就相当于最小点覆盖,树上的最小点覆盖可以用树形dp算出,设dp[i][0]代表i这个点不选最小点数,dp[i][1]代表i这个点要选最小点数,那么从根节点开始每一个数dp[i][1] = min(dp[j][0], dp[j][1]);dp[i][0] = dp[j][1];可以算出最大匹配
#include <bits/stdc++.h> #define ll long long #define maxn 100100 using namespace std; int dp[maxn][2], dir[maxn]; vector<int >G[maxn]; namespace fastIO { #define BUF_SIZE 1000000 //fread -> read bool IOerror = 0; inline char nc() { static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; if(p1 == pend) { p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin); if(pend == p1) { IOerror = 1; return -1; } } return *p1++; } inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; } inline void read(int &x) { char ch; while(blank(ch = nc())); if(IOerror) return; for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); } }; using namespace fastIO; inline void dfs(int x){ dp[x][0] = 0; dp[x][1] = 1; dir[x] = 1; for(int i=0;i<G[x].size();i++){ int u = G[x][i]; if(dir[u] == 1) continue; dfs(u); dp[x][1] += min(dp[u][0], dp[u][1]); dp[x][0] += dp[u][1]; } } int main(){ int T, k, n, t, root, ans; read(T); while(T--){ read(n);read(k); for(int i=1;i<=n;i++) G[i].clear(); memset(dir, 0, sizeof(dir)); for(int i=1;i<n;i++){ read(t); G[i+1].push_back(t); G[t].push_back(i+1); } for(int i=1;i<=n;i++) if(G[i].size() == 1){ root = i; break; } dfs(root); ans = min(dp[root][0], dp[root][1]); if(ans*2 > k) printf("%d\n", (k+1)/2); else printf("%d\n", (k-ans)); } return 0; } /* 4 4 1 2 3 */
posted on 2017-08-25 21:42 2855669158 阅读(138) 评论(0) 编辑 收藏 举报