您的位置:首页 > 其它

HDU - 6178 Monkeys 【树上的最大匹配 + 读入挂优化】

2017-10-12 00:05 316 查看
传送门

//题意: 给定一个树, 每个结点上可以占据一个猴子, 问最少留下多少条边使得k个猴子都占据一个结点, 并且每个猴子必须都要有另外一个有猴子的结点和他相连才行.

//思路:简单的说就是,总是先满足一条边占据两个猴子是最优的, 然后这类边占据完了后, 在多一个猴子就需要再多一条边即可. 这个就是树上的二分匹配, 建图跑二分匹配肯定不行, 所以用树形dp, 或者贪心的方法On可求出最大匹配数, 但是要卡读数据, 所以还需要一个读入挂(相当于模板吧)! 我这用的贪心.

AC Code

const int maxn = 1e5+5;
int cas=1;
struct FastIO
{
static const int S = 2*100;
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar()
{
static char buf[S];
static int len = 0, pos = 0;
if (pos==len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos==len) exit(0);
return buf[pos ++];
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while(c<=32) c = xchar();
if(c=='-') s = -1, c = xchar();
for(;'0'<=c && c<='9';c=xchar()) x = x*10+c-'0';
return x * s;
}
~FastIO()
{
if(wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
}io;
vector<int>g[maxn];
int mark[maxn];
int res;
void dfs(int u,int fa)
{
int cnt = 0,tt = 0;
for(int i=0;i<g[u].size();i++){
int to = g[u][i];
if(to == fa) continue;
dfs(to,u);
cnt++;   //有多少个子节点
tt += mark[to];   //子节点中有多少个已经配对了的.
}//即贪心的从叶子结点开始匹配,可以匹配就匹配,然后一直进行完.
if(cnt - tt >= 1) res++, mark[u] = 1;
//此时u可以和子节点的某一个进行匹配,那就进行一次.
}

void solve()
{
int n,k;
n = io.xint(); k = io.xint();
for(int i=1;i<=n;i++) g[i].clear();
Fill(mark,0); res = 0;
for(int i=2;i<=n;i++){
int u = io.xint();
g[i].push_back(u);
g[u].push_back(i);
}
dfs(1,-1);
if(res*2 >= k) printf("%d\n",(k+1)/2);
else printf("%d\n",k - res);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: