Description

给定\(N(N\leq 10000)\)个点的树,要求用最少的路径覆盖树边。路径之间可以有交点,不能有交边。问最少需要几条路径以及在第一问的基础上最长的路径最短是多少?

Solution

第一问对于每个点考虑它与它的孩子之间的边

如果能两两消掉是最好的,贡献就是\(\frac{deg[i]-1}2\),否则就要额外多出一条边,贡献是\(\frac{deg[i]-1}2+1\)。

第二问就是二分答案了

判断\(\leq mid\) 是否可行

可以一遍 \(dfs\) 求出 \(f[i]\) 表示第 \(i\) 个点最短向下延伸多长

如何求这个 \(f[i]\) ?

需要对点的孩子个数分奇偶性讨论

如果它有偶数个孩子,那么最理想的情况就是让他们两两匹配,这个点的 \(f\) 值为 \(0\)。

如果事与愿违(我写个博客怎么都这么多骚话),就可以尝试拿出两个孩子,让一个孩子的链断在这个点,这个点接上另一个孩子的链,其他孩子两两匹配。

如果有奇数个孩子,那就是拿出一个孩子,让这个点接上这个孩子的链,其他孩子两两匹配。

判断两两匹配可以再套个二分。

Code

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cctype>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using std::min;
using std::max;
using std::swap;
using std::vector;
const int N=10005;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define mp(A,B) std::make_pair(A,B) int head[N],f[N];
int n,cnt,g[N],deg[N]; struct Edge{
int to,nxt;
}edge[N<<1]; void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
} int getint(){
int X=0,w=0;char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} bool check(int l,int r,int x,int mid){
while(l<r){
if(l==x) l++;
if(r==x) r--;
if(g[l]+g[r]>mid) return 0;
l++,r--;
} return 1;
} bool dfs(int now,int fa,int x){
int cnts=0;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;cnts++;
if(to!=fa) if(!dfs(to,now,x)) return 0;
if(f[to]+1>x) return 0;
} if(cnts==1 and now!=1) return f[now]=0,1;
int pos=0;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(to==fa) continue;
g[++pos]=f[to]+1;
} std::sort(g+1,g+1+pos);
if(pos%2==0){ //偶数
int flag=0;
for(int i=1;i<=pos/2;i++)
if(g[i]+g[pos-i+1]>x)
flag=1;
if(!flag) return f[now]=0,1;
if(now==1) return 0;
int l=1,r=pos-1,ans=0;
while(l<=r){
int mid=l+r>>1;
if(g[mid]>x) {l=mid+1;continue;}
if(check(1,pos-1,mid,x)) ans=mid,r=mid-1;
else l=mid+1;
} if(!ans) return 0;
f[now]=g[ans];return 1;
} else{
if(pos==1) return g[1]<=x?f[now]=g[1],1:0;
int l=1,r=pos,ans=0;
while(l<=r){
int mid=l+r>>1;
if(g[mid]>x) {l=mid+1;continue;}
if(check(1,pos,mid,x)) ans=mid,r=mid-1;
else l=mid+1;
} if(!ans) return 0;
f[now]=g[ans];return 1;
}
} signed main(){
// system("fc 11.out out.txt");
// freopen("11.in","r",stdin);//freopen("out.txt","w",stdout);
n=getint();
for(int i=1;i<n;i++){
int x=getint(),y=getint();
add(x,y);add(y,x);deg[x]++;deg[y]++;
} int ans=1;
for(int i=1;i<=n;i++) ans+=(deg[i]-1)/2;
printf("%d ",ans);
int l=0,r=n-1;ans=0;
while(l<=r){
int mid=l+r>>1;
if(dfs(1,0,mid)){
if(f[1]<=mid) ans=mid,r=mid-1;
else l=mid+1;
}
else l=mid+1;
} printf("%d\n",ans);
return 0;
}//youngneal

[POI2004] SZN的更多相关文章

  1. 【BZOJ2067】[Poi2004]SZN 二分+树上贪心

    [BZOJ2067][Poi2004]SZN Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一 ...

  2. 2067: [Poi2004]SZN——树上贪心+二分

    题目大意: 给一棵树.求用最少的链覆盖这棵树(链不能相交),在这个基础上求最长的链最短可以是多少. n<=10000 题解: 肯定先处理第一问: 答案:$\sum_(du[i]-1)/2+1$ ...

  3. bzoj2067: [Poi2004]SZN

    Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一些顶点和特定数量的边构成. 每个顶点都可以连向 ...

  4. 【BZOJ2067】[Poi2004]SZN

    题解: 比上一题水多了 首先树上贪心,肯定要考虑儿子 然后我们会发现这个东西就是要先把儿子连起来 然后如果儿子个数为奇数我们可以把这一条和它连向父亲的并在一起 由于根没有父亲所以要单独考虑 答案就是s ...

  5. bzoj 2067 [Poi2004]SZN——二分+贪心

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2067 最少的线段可以贪心地想出来.(结果还是写错了)就是偶数孩子可以自己配对,奇数孩子要带一 ...

  6. bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】

    第一问就是Σ(deg[u]-1)/2+1 第二问是二分,判断的时候考虑第一问的贪心规则,对于奇度数的点,两两配对之后一条延伸到上面:对于欧度数的点,两两配对或者deg[u]-2的点配对,然后一条断在这 ...

  7. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

随机推荐

  1. 《Linux就该这么学》第二天课程

    秦时明月经典语录:很多人被命运安排,而我安排命运.——卫庄 今天介绍了VM 虚拟机的安装以及Linux系统的安装,还讲解了Linux内核 RPM:降低软件的安装难度 源代码+安装规则→将程序源代码与安 ...

  2. SSM框架整合(Spring+SpringMVC+MyBatis+Oracle)

    1.开发环境搭建以及创建Maven Web项目 参看之前的博文[确保maven web项目不报错]:http://www.cnblogs.com/cainiaomahua/p/6306476.html ...

  3. Jmeter小技巧以及问题集合

    一.JDBC Request与BeanShell PostProcessor的结合使用 JDBCRequest部分   BeanShell PostProcessor配置项 二.if控制器的用法 三. ...

  4. async/await让你的代码更加优雅

    一. 回调地狱:回调函数里面嵌套着回调函数嵌套着回调函数”,这就是被传说中的“回调地狱callbackHell () { const api = new Api() let user, friends ...

  5. delegate的Invoke和BeginInvoke方法

    C#中的控件和delegate委托方法都有Invoke和BeginInvoke方法,控件的这两个方法网上讲得很多, 这里就不多说了,下面讲一下delegate的Invoke和BeginInvoke方法 ...

  6. 调用opencv相关函数,从视频流中提取出图片序列&&&&jpg图片序列,转化成avi格式视频

    /************************ @HJ 2017/3/30 参考http://blog.sina.com.cn/s/blog_4b0020f301010qcz.html修改的代码 ...

  7. open:在终端打开文件|应用程序等

    1. 需求&解决方案 打开文件 或url(用默认应用程序): $ open fileName 打开文件 或url(用指定应用程序): $ open -a appName fileName ## ...

  8. shell脚本基础教程

    一.什么是shell: shell解释:引用别人的话说:“Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.” 简而言之, ...

  9. idea集成maven

    1 下载maven并解压 至 http://archive.apache.org/dist/maven/maven-3/下载zip包,下载后的包如下: 解压到安装目录下:如:D:\software,解 ...

  10. Django(序列化、SweetAlert插件)

    day72 参考:https://www.cnblogs.com/liwenzhou/p/8718861.html#autoid-6-1-2 前端序列化 后端序列化 day73中 补充一个SweetA ...