【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys
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的更多相关文章
- HDU 4607 Park Visit 两次DFS求树直径
两次DFS求树直径方法见 这里. 这里的直径是指最长链包含的节点个数,而上一题是指最长链的路径权值之和,注意区分. K <= R: ans = K − 1; K > R: ans = ...
- HDU 6178 Monkeys(树上的二分匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:现在有一n个顶点的树形图,还有k只猴子,每个顶点只能容纳一只猴子,而且每只猴子至少和另外一只猴子通过 ...
- 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 ...
- HDU - 6178:Monkeys (贪心&树上最大匹配输&输入优化)
There is a tree having N vertices. In the tree there are K monkeys (K <= N). A vertex can be occu ...
- 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 ...
- hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)
Cyclic Tour Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total ...
- HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...
- HDU 4607 Park visit (求树的直径)
解题思路: 通过两次DFS求树的直径,第一次以随意点作为起点,找到距离该点距离最远的点,则能够证明这个点一定在树的直径上,然后以该点为起点进行DFS得到的最长路就是树的直径. 最后的询问,假设K &l ...
- 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组
题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...
随机推荐
- codevs 2728 整数帝国问题(水题日常)
时间限制: 1 s 空间限制: 16000 KB 题目等级 : 白银 Silver 题目描述 Description 在很久以前,在遥远的东方,有一个整数帝国,它里面里居住着大量的正整数,了缓解都 ...
- 使用ABAP编程实现对微软Office Word文档的操作
SAP ABAP里提供了一个标准的类CL_DOCX_DOCUMENT,提供了本地以".docx"结尾的微软Office word文档的读和写操作. 本文介绍了ABAP类CL_DOC ...
- 系统相册中获取gif图片 保证取到的图片不会改变
NSURL *imageRefURL = [info valueForKey:UIImagePickerControllerReferenceURL]; ...
- 图片,二进制,oracle数据库
图片在oracle数据库中一般以二进制存在,存储类型是blob,然而clob类型一般存储的是大于4000的字符,不能用来存储图像这样的二进制内容,下面展示一下实现图像,二进制,oracle 数据库的应 ...
- (转)SpringMVC学习(二)——SpringMVC架构及组件
http://blog.csdn.net/yerenyuan_pku/article/details/72231385 相信大家通过前文的学习,已经对SpringMVC这个框架多少有些理解了.还记得上 ...
- python基础一 day13 复习
# 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...
- 小白安装python软件
首先下载:anaconda3.x 下载方式:百度搜索 清华镜像anaconda https://mirrors.tuna.tsinghua.edu.cn/help/anacond ...
- Codeforces Round #272 (Div. 2)-B. Dreamoon and WiFi
http://codeforces.com/contest/476/problem/B B. Dreamoon and WiFi time limit per test 1 second memory ...
- Bootstrap历练实例:验证状态
验证状态 Bootstrap 包含了错误.警告和成功消息的验证样式.只需要对父元素简单地添加适当的 class(.has-warning. .has-error 或 .has-success)即可使用 ...
- shell脚本,awk如何处理文件中上下关联的两行。
文件d.txt如下内容 ggg 1portals: 192.168.5.41:3260werew 2portals: 192.168.5.43:3260 如何把文件d.txt内容变为如下内容 ggg ...