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. 兼容IE8的flash上传框架"uploadify"自定义上传按钮样式的办法

    (uploadify版本:3.2.1 ) 因为公司业务的原因,所做的项目需要兼容IE8,因此做的上传插件无奈选择的是基于flash的uploadify. 由于是基于flash的,所以使用过程中,难以给 ...

  2. PHP 百万级数据导出方案(多 CSV 文件压缩)

    ps:来源 :https://laravel-china.org/articles/15944/php-million-level-data-export-scheme-multi-csv-file- ...

  3. drf3 Serializers 序列化组件

    为什么要用序列化组件 做前后端分离的项目,我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 给前端数据的时候都要转成json格式,那就需要对从数据库拿到的数据进行序列化. ...

  4. LwIP协议栈接口

    协议栈api函数 1.netconn_new      //UDP    TCP struct netconn*netconn_new(enum netconn_type t) 为新连接申请一个连接结 ...

  5. stm32手册上的英文

    crystal-less 无晶振 USB  FS(Full-speed)此外还有High-speed接口(简称HS),Low-speed接口(简称LS) frequency频率 CRC(Cyclic ...

  6. uasrt配置

    Universal Synchronous/Asynchronous Receiver/Transmitter 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式.同步要有一个 ...

  7. verilog HDL-并行语句之assign

    线网型数据对象: 是verilog hdl常用数据对象之一,起到电路节点之间的互联作用,类似于电路板上的导线. wire是verilog hdl默认的线网型数据对象. 线网型数据对象的读操作在代码任何 ...

  8. vscode调试angular

    之前在Asp.net MVC + Angular1 的项目中,要调试前台代码都是用浏览器的开发者工具,使用正常,也没有感觉太大的不方便. 后来接触Angular2项目,因为它是要经过编译的,所以在浏览 ...

  9. 「WC2018」州区划分(FWT)

    「WC2018」州区划分(FWT) 我去弄了一个升级版的博客主题,比以前好看多了.感谢 @Wider 不过我有阅读模式的话不知为何 \(\text{LATEX}\) 不能用,所以我就把这个功能删掉了. ...

  10. docker:(2)通过Dockerfile构建镜像并发布web项目

    上一篇讲解了docker的基本使用 http://www.cnblogs.com/xiaochangwei/p/8204511.html 虽然通过修改获取到的镜像可以达到使用目的,但是多操作几次就会发 ...