[POI2004] SZN
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的更多相关文章
- 【BZOJ2067】[Poi2004]SZN 二分+树上贪心
[BZOJ2067][Poi2004]SZN Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一 ...
- 2067: [Poi2004]SZN——树上贪心+二分
题目大意: 给一棵树.求用最少的链覆盖这棵树(链不能相交),在这个基础上求最长的链最短可以是多少. n<=10000 题解: 肯定先处理第一问: 答案:$\sum_(du[i]-1)/2+1$ ...
- bzoj2067: [Poi2004]SZN
Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一些顶点和特定数量的边构成. 每个顶点都可以连向 ...
- 【BZOJ2067】[Poi2004]SZN
题解: 比上一题水多了 首先树上贪心,肯定要考虑儿子 然后我们会发现这个东西就是要先把儿子连起来 然后如果儿子个数为奇数我们可以把这一条和它连向父亲的并在一起 由于根没有父亲所以要单独考虑 答案就是s ...
- bzoj 2067 [Poi2004]SZN——二分+贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2067 最少的线段可以贪心地想出来.(结果还是写错了)就是偶数孩子可以自己配对,奇数孩子要带一 ...
- bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】
第一问就是Σ(deg[u]-1)/2+1 第二问是二分,判断的时候考虑第一问的贪心规则,对于奇度数的点,两两配对之后一条延伸到上面:对于欧度数的点,两两配对或者deg[u]-2的点配对,然后一条断在这 ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
随机推荐
- shiro的rememberMe不生效
问题描述:已经设置了map.put("/**", "user"),但是查看网页Cookie没有值. 问题查思路: 1.确定使用UserFilter过滤器,因为只 ...
- wince sqlite c#
无法找到 PInvoke DLL“SQLite.Interop.084.dll 按下面步骤操作
- Maven学习 五 Maven项目创建(1)jar项目
第一步:Maven项目的创建 File->new->Maven project. 点击下一步 上方的两个多选框选上,第一个是不使用archetype 原型模板,第二个是使用默认工作空间 点 ...
- ubuntu下搭建一个数据化处理的开发环境
1.搭建matplotlib环境 构建matplotlib运行环境,需要满足相关软件环境. numpy库提供大数据集的数据的数据结构和数学方法.诸如元组.列表或字典等python的默认数据结构同样可以 ...
- js-运动函数包
function move(obj, attr, dir, target, endFn) { clearInterval(obj.timer) // 避免全局变量,所以要用oBox.timer di ...
- 如何将uniurlframe中html调用delphi的函数
uniGUI总群中台中cmj朋友为我们总结了如下内容,对于利用delphi+uniGUI开发应用,可以说是精品,必须掌握. 一句话,如何在html与delphi间交互代码,是最好的答案. [Clien ...
- 请找出至少一个由递推关系 a(i) = a(i – 1) + a(i – 2) 生成的数列,使得当 n 趋于 (√5+1)/2的数列
寻找前后两项比值趋于 (√5+1)/2的广义Fibonacci数列 找到了一个帖子:这个帖子 //待补充
- Increasing Subsequence (hard version)
首先讲一下题目大意:给你n个数,然后从最左边(L)或者最右边(R)取一个数生成出一个新的序列,对于这个序列的要求是递增的(注意是递增的,不能存在等于的情况)问这个序列有多长.并打印此操作. 这题就是忘 ...
- maya2016卸载/安装失败/如何彻底卸载清除干净maya2016注册表和文件的方法
maya2016提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装maya2016失败提示maya2016安装未完成,某些产品无法安装,也有时候想重新安装maya ...
- [git] 基本原理
1. 基本原理 工作目录:本地项目所在目录 暂存区: 被 git 所管理的文件 本地仓库:本地的版本仓库,一般的提交操作会将变更信息先提交到本地仓库的版本库中 远程仓库:远程的版本仓库,将变更信 ...