【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 ...
随机推荐
- Node.js 打造实时多人游戏框架
在 Node.js 如火如荼发展的今天,我们已经可以用它来做各种各样的事情.前段时间UP主参加了极客松活动,在这次活动中我们意在做出一款让“低头族”能够更多交流的游戏,核心功能便是 Lan Party ...
- ADO1
1. 新建Web窗体 客户端控件:html控件 服务器控件:用的比较少 2. 数据库连接 protected void btnLogin_Click(object sender, EventArgs ...
- COFF文件格式
链接器 目录 一 COFF-Common Object File Format-通用对象文件格式... 3 COFF的文件格式与结构体... 4 文件头... 5 numberOfSections(区 ...
- 找出指定文件夹中的所有以txt结尾的文件,包括所有嵌套的子文件夹
# coding:utf-8 import os, re for i in os.walk('d:'+os.sep): for txt in i[2]: try: ...
- iOS7.1企业应用"无法安装应用程序 因为证书无效"的解决方案
今天升级了iOS7.1后发现通过之前的url无法安装企业应用了,一直提示“无法安装应用程序 因为http://xxx.xxx.xxx证书无效”,折腾了一番,终于在StackOverFlow上找到了答案 ...
- 制作新的train,test数据集
之前的数据集的train和test是直接按照网上下载的数据的前7000个作为训练集,后2212个作为测试集.看得出来,这个数据集是由开车录制视频转换来的图片数据,后面2000多个图片的场景和前面的场景 ...
- AEE加密解密
from Crypto.Cipher import AESfrom binascii import b2a_hex, a2b_hex class AesHandler(object): def ...
- HTML5服务器发送事件(Server-Send Events)
HTML5服务器发送事件是允许获得来自服务器的更新. server-sent事件-单向传递消息,表示网页自动获取来自服务器的更新. 其中有一个重要的对象,eventsource对象是用来接收服务器发送 ...
- ios 之CGRectMake
首先要弄懂几个基本的概念. 一)三个结构体:CGPoint.CGSize.CGRect 1. CGPoint [plain] view plaincopy /* Points. */ struc ...
- fshc之请求仲裁机制的代码分析
always@(posedge spi_clk or negedge spiclk_rst_n) begin if(~spiclk_rst_n) arbiter2cache_ack_r <='b ...