http://acm.hdu.edu.cn/showproblem.php?pid=6178

【题意】

  • 给定一棵有n个结点的树,现在有k个猴子分布在k个结点上,我们可以删去树上的一些边,使得k个猴子每个猴子都至少和其他一个猴子相连
  • 问树上最少保留多少条边

【思路】

  • 每个猴子要至少和一个猴子相连,考虑保留的边最少,那么最优的情况一定是一条边的两个顶点放两个猴子,这些边的顶点都不重合
  • 我们现在要找到给定的树中最多有多少条这样的边,即最大二分匹配
  • O(n)的DFS,对于每个结点,优先与叶子结点形成一条边

【AC】

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
namespace IO
{
const int MX=1e8;
char buf[MX];
int c,sz;
void begin()
{
c=;
sz=fread(buf,,MX,stdin);
}
inline bool read(int &x)
{
while(c<sz && buf[c]!='-' && (buf[c]<''||buf[c]>'')) ++c;
if(c>=sz) return false;
bool flag=;
if(buf[c]=='-') flag=,++c;
for(x=;c<sz&&buf[c]>=''&&buf[c]<='';++c)
x=x*+buf[c]-'';
if(flag) x=-x;
return true;
}
} int n,k;
const int maxn=1e5+;
const int maxm=maxn*;
bool vis[maxn];
struct edge
{
int to;
int nxt;
}e[maxm];
int head[maxn];
int tot;
//int dp[maxn][2];
int flag;
int cnt;
void init()
{
memset(head,-,sizeof(head));
tot=;
// memset(dp,0,sizeof(dp));
memset(vis,false,sizeof(vis));
cnt=;
}
void addedge(int u,int v)
{
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
} void dfs(int u,int pa)
{
for(int i=head[u];i!=-;i=e[i].nxt)
{
int v=e[i].to;
if(v==pa) continue;
dfs(v,u);
if(!vis[u]&&!vis[v])
{
cnt++;
vis[u]=vis[v]=true;
}
}
}
int main()
{
IO::begin();
int T;
IO::read(T);
// scanf("%d",&T);
while(T--)
{
init();
// scanf("%d%d",&n,&k);
IO::read(n);IO::read(k);
int x;
for(int i=;i<=n;i++)
{
//scanf("%d",&x);
IO::read(x);
addedge(i,x);
addedge(x,i);
}
dfs(,-);
int tmp=cnt*;
int ans;
if(k<=tmp)
{
ans=k/;
if(k%) ans++;
}
else
{
ans=cnt+k-tmp;
}
printf("%d\n",ans);
}
return ;
}

贪心,优先选叶子结点

 #include<bits/stdc++.h>
namespace fastIO {
#define BUF_SIZE 1100000
#define OUT_SIZE 1100000
#define ll long long
// fread->read
bool IOerror = ;
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, , BUF_SIZE, stdin);
if (pend == p1) {
IOerror = ;
return -;
}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
bool sign = ;
char ch = nc();
x = ;
for (; blank(ch); ch = nc())
;
if (IOerror) return;
if (ch == '-') sign = , ch = nc();
for (; ch >= '' && ch <= ''; ch = nc()) x = x * + ch - '';
if (sign) x = -x;
}
inline void read(ll &x) {
bool sign = ;
char ch = nc();
x = ;
for (; blank(ch); ch = nc())
;
if (IOerror) return;
if (ch == '-') sign = , ch = nc();
for (; ch >= '' && ch <= ''; ch = nc()) x = x * + ch - '';
if (sign) x = -x;
}
inline void read(double &x) {
bool sign = ;
char ch = nc();
x = ;
for (; blank(ch); ch = nc())
;
if (IOerror) return;
if (ch == '-') sign = , ch = nc();
for (; ch >= '' && ch <= ''; ch = nc()) x = x * + ch - '';
if (ch == '.') {
double tmp = ;
ch = nc();
for (; ch >= '' && ch <= ''; ch = nc()) tmp /= 10.0, x += tmp * (ch - '');
}
if (sign) x = -x;
}
inline void read(char *s) {
char ch = nc();
for (; blank(ch); ch = nc())
;
if (IOerror) return;
for (; !blank(ch) && !IOerror; ch = nc()) *s++ = ch;
*s = ;
}
inline void read(char &c) {
for (c = nc(); blank(c); c = nc())
;
if (IOerror) {
c = -;
return;
}
}
// getchar->read
inline void read1(int &x) {
char ch;
int bo = ;
x = ;
for (ch = getchar(); ch < '' || ch > ''; ch = getchar())
if (ch == '-') bo = ;
for (; ch >= '' && ch <= ''; x = x * + ch - '', ch = getchar())
;
if (bo) x = -x;
}
inline void read1(ll &x) {
char ch;
int bo = ;
x = ;
for (ch = getchar(); ch < '' || ch > ''; ch = getchar())
if (ch == '-') bo = ;
for (; ch >= '' && ch <= ''; x = x * + ch - '', ch = getchar())
;
if (bo) x = -x;
}
inline void read1(double &x) {
char ch;
int bo = ;
x = ;
for (ch = getchar(); ch < '' || ch > ''; ch = getchar())
if (ch == '-') bo = ;
for (; ch >= '' && ch <= ''; x = x * + ch - '', ch = getchar())
;
if (ch == '.') {
double tmp = ;
for (ch = getchar(); ch >= '' && ch <= ''; tmp /= 10.0, x += tmp * (ch - ''), ch = getchar())
;
}
if (bo) x = -x;
}
inline void read1(char *s) {
char ch = getchar();
for (; blank(ch); ch = getchar())
;
for (; !blank(ch); ch = getchar()) *s++ = ch;
*s = ;
}
inline void read1(char &c) {
for (c = getchar(); blank(c); c = getchar())
;
}
// scanf->read
inline void read2(int &x) {
scanf("%d", &x);
}
inline void read2(ll &x) {
#ifdef _WIN32
scanf("%I64d", &x);
#else
#ifdef __linux
scanf("%lld", &x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void read2(double &x) {
scanf("%lf", &x);
}
inline void read2(char *s) {
scanf("%s", s);
}
inline void read2(char &c) {
scanf(" %c", &c);
}
inline void readln2(char *s) {
gets(s);
}
// fwrite->write
struct Ostream_fwrite {
char *buf, *p1, *pend;
Ostream_fwrite() {
buf = new char[BUF_SIZE];
p1 = buf;
pend = buf + BUF_SIZE;
}
void out(char ch) {
if (p1 == pend) {
fwrite(buf, , BUF_SIZE, stdout);
p1 = buf;
}
*p1++ = ch;
}
void print(int x) {
static char s[], *s1;
s1 = s;
if (!x) *s1++ = '';
if (x < ) out('-'), x = -x;
while (x) *s1++ = x % + '', x /= ;
while (s1-- != s) out(*s1);
}
void println(int x) {
static char s[], *s1;
s1 = s;
if (!x) *s1++ = '';
if (x < ) out('-'), x = -x;
while (x) *s1++ = x % + '', x /= ;
while (s1-- != s) out(*s1);
out('\n');
}
void print(ll x) {
static char s[], *s1;
s1 = s;
if (!x) *s1++ = '';
if (x < ) out('-'), x = -x;
while (x) *s1++ = x % + '', x /= ;
while (s1-- != s) out(*s1);
}
void println(ll x) {
static char s[], *s1;
s1 = s;
if (!x) *s1++ = '';
if (x < ) out('-'), x = -x;
while (x) *s1++ = x % + '', x /= ;
while (s1-- != s) out(*s1);
out('\n');
}
void print(double x, int y) {
static ll mul[] = {, , , , , , , , , , 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL, 1000000000000000LL, 10000000000000000LL, 100000000000000000LL};
if (x < -1e-) out('-'), x = -x;
x *= mul[y];
ll x1 = (ll) floor(x);
if (x - floor(x) >= 0.5) ++x1;
ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y];
print(x2);
if (y > ) {
out('.');
for (size_t i = ; i < y && x3 * mul[i] < mul[y]; out(''), ++i)
;
print(x3);
}
}
void println(double x, int y) {
print(x, y);
out('\n');
}
void print(char *s) {
while (*s) out(*s++);
}
void println(char *s) {
while (*s) out(*s++);
out('\n');
}
void flush() {
if (p1 != buf) {
fwrite(buf, , p1 - buf, stdout);
p1 = buf;
}
}
~Ostream_fwrite() {
flush();
}
} Ostream;
inline void print(int x) {
Ostream.print(x);
}
inline void println(int x) {
Ostream.println(x);
}
inline void print(char x) {
Ostream.out(x);
}
inline void println(char x) {
Ostream.out(x);
Ostream.out('\n');
}
inline void print(ll x) {
Ostream.print(x);
}
inline void println(ll x) {
Ostream.println(x);
}
inline void print(double x, int y) {
Ostream.print(x, y);
}
inline void println(double x, int y) {
Ostream.println(x, y);
}
inline void print(char *s) {
Ostream.print(s);
}
inline void println(char *s) {
Ostream.println(s);
}
inline void println() {
Ostream.out('\n');
}
inline void flush() {
Ostream.flush();
}
// puts->write
char Out[OUT_SIZE], *o = Out;
inline void print1(int x) {
static char buf[];
char *p1 = buf;
if (!x) *p1++ = '';
if (x < ) *o++ = '-', x = -x;
while (x) *p1++ = x % + '', x /= ;
while (p1-- != buf) *o++ = *p1;
}
inline void println1(int x) {
print1(x);
*o++ = '\n';
}
inline void print1(ll x) {
static char buf[];
char *p1 = buf;
if (!x) *p1++ = '';
if (x < ) *o++ = '-', x = -x;
while (x) *p1++ = x % + '', x /= ;
while (p1-- != buf) *o++ = *p1;
}
inline void println1(ll x) {
print1(x);
*o++ = '\n';
}
inline void print1(char c) {
*o++ = c;
}
inline void println1(char c) {
*o++ = c;
*o++ = '\n';
}
inline void print1(char *s) {
while (*s) *o++ = *s++;
}
inline void println1(char *s) {
print1(s);
*o++ = '\n';
}
inline void println1() {
*o++ = '\n';
}
inline void flush1() {
if (o != Out) {
if (*(o - ) == '\n') *--o = ;
puts(Out);
}
}
struct puts_write {
~puts_write() {
flush1();
}
} _puts;
inline void print2(int x) {
printf("%d", x);
}
inline void println2(int x) {
printf("%d\n", x);
}
inline void print2(char x) {
printf("%c", x);
}
inline void println2(char x) {
printf("%c\n", x);
}
inline void print2(ll x) {
#ifdef _WIN32
printf("%I64d", x);
#else
#ifdef __linux
printf("%lld", x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void println2(ll x) {
print2(x);
printf("\n");
}
inline void println2() {
printf("\n");
}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
typedef long long ll;
int n,k;
const int maxn=1e5+;
const int maxm=maxn*;
struct edge
{
int to;
int nxt;
}e[maxm];
int head[maxn];
int tot;
int dp[maxn][]; void init()
{
memset(head,-,sizeof(head));
tot=;
memset(dp,,sizeof(dp));
}
void addedge(int u,int v)
{
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
} bool dfs(int u,int pa)
{
int flag=;
dp[u][]=;
for(int i=head[u];i!=-;i=e[i].nxt)
{
int v=e[i].to;
if(v==pa) continue;
if(dfs(v,u))
{
flag=;
}
dp[u][]+=dp[v][];
}
if(flag)
{
dp[u][]=dp[u][]+;
return false;
}
else
{
dp[u][]=dp[u][];
return true;
}
}
int main()
{
int T;
//scanf("%d",&T);
read(T);
//cout<<T<<endl;
while(T--)
{
init();
read(n);
read(k);
//cout<<n<<k<<endl;
//scanf("%d%d",&n,&k);
int x;
for(int i=;i<=n;i++)
{
read(x);
//scanf("%d",&x);
addedge(i,x);
addedge(x,i);
}
dfs(,-);
int cnt=dp[][];
int tmp=cnt*;
int ans;
if(k<=tmp)
{
ans=k/;
if(k%) ans++;
}
else
{
ans=cnt+k-tmp;
}
printf("%d\n",ans);
}
return ;
}

树形dp

树形dp的代码比赛是wa了,赛后才发现,原来是我dfs里开了全局变量flag,flag在其他层里被修改,改成局部变量就A了orz

【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys的更多相关文章

  1. HDU 4607 Park Visit 两次DFS求树直径

    两次DFS求树直径方法见 这里. 这里的直径是指最长链包含的节点个数,而上一题是指最长链的路径权值之和,注意区分. K <= R: ans = K − 1; K > R:   ans = ...

  2. HDU 6178 Monkeys(树上的二分匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:现在有一n个顶点的树形图,还有k只猴子,每个顶点只能容纳一只猴子,而且每只猴子至少和另外一只猴子通过 ...

  3. NBUT 1186 Get the Width(DFS求树的宽度,水题)

    [1186] Get the Width 时间限制: 1000 ms 内存限制: 65535 K 问题描述 It's an easy problem. I will give you a binary ...

  4. HDU - 6178:Monkeys (贪心&树上最大匹配输&输入优化)

    There is a tree having N vertices. In the tree there are K monkeys (K <= N). A vertex can be occu ...

  5. HDU 3861 The King’s Problem(tarjan缩点+最小路径覆盖:sig-最大二分匹配数,经典题)

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  6. hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total ...

  7. HDU4612+Tarjan缩点+BFS求树的直径

    tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...

  8. HDU 4607 Park visit (求树的直径)

    解题思路: 通过两次DFS求树的直径,第一次以随意点作为起点,找到距离该点距离最远的点,则能够证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径. 最后的询问,假设K &l ...

  9. 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组

    题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...

随机推荐

  1. ARC和MRC混合模式下的编译问题

    在一个支持ARC (Automatic Reference Counting)的项目中,有时候需要禁止其中几个文件使用ARC模式编译(比如你用了第三方不支持ARC的类库).这时就要点击工程文件,在ta ...

  2. Scalatra

    SBT和giter8 在你开始着手之前,你需要安装两个工具(我假设你已经安装了JDK1.6+).我将给你提供简缩的安装指令,详细版的安装指令可通过 下面的scalatra页面找到( http://ww ...

  3. 快学UiAutomator新建第一个测试工程

    1.打开Eclipse 2.新建一个java项目,包 3.增加build path,加载需要的库文件jar包 4.新建测试类,继承UIAutomatorTestCase 5.编写测试用例,方法名必须t ...

  4. Freemarker入门小案例(生成静态网页的其中一种方式)

    其实生成静态网页的方式有好多种,我昨天看了一下,Freemarker是其中一种,但是Freemarker现在我们都用得比较少了,现在用得ActiveMQ用来发送信息到静态页面,不过想了一下这个小东西, ...

  5. Bootstrap历练实例:垂直的按钮组

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  6. iOS开发--使用OpenSSL生成私钥和公钥的方法

    最近要在新项目中使用支付宝钱包进行支付,所以要调研对接支付宝的接口,支付宝开放平台采用了RSA安全签名机制,开发者可以通过支付宝   公钥验证消息来源,同时可使用自己的私钥对信息进行加密,所以需要在本 ...

  7. ios之UITextView

    我们计划创建UITextView,实现UITextViewDelegate协议方法,使用NSLog检查该方法何时被调用.我们还会接触到如何在TextView中限制字符的数量,以及如何使用return键 ...

  8. 将 PROTOCOL 的方法声明为 MUTATING

    将 PROTOCOL 的方法声明为 MUTATING 由 王巍 (@ONEVCAT) 发布于 2014/08/17 Swift 的 protocol 不仅可以被 class 类型实现,也适用于 str ...

  9. vue axios 请求本地接口端口不一致出现跨域设置代理

    首先在config下面的index.js,设置跨域代理 在axios请求的时候     用'/api/' 替代baseURL 最重要的就是设置完必须重新 npm run dev 否则不生效

  10. 【DB_MySQL】 limit——取查询结果的子集

    语法:select * from student limit beginIndex,length; 这里结果集的下标同数组一样从0开始,beginIndex表示起始位置,length表示从beginI ...