BZOJ2067: [Poi2004]SZN【贪心DP】

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20181220_xiang_m_y/article/details/102564783

题目描述:

n个点的树,问最少需要多少条线才能覆盖所有边,以及最少用线的情况下最长线的最短长度。
一条边只能被覆盖一次,线与线之间点可以相交。
n<=10000

题目分析:

我们先不考虑最少用线。
一个点 i i (非根节点),由于它的父亲要被覆盖,所以最少用线的情况下这条线一定可以往其中一个儿子延伸,其余儿子连到自己的这条线就要两两配对,用 d [ i ] d[i] 表示 i i 的度数,则 i i 的贡献就是 d [ i ] 1 2 \frac {d[i]-1}2 (不计连向上面的边),根节点没有向上的边,所以要加一。

通过上面这个贪心就可以大致发现线的形成方式是固定的,即 i i 子树中用多少条线的数量已经固定了,那么就只需要考虑向上连的这条线的长度了。
f [ i ] f[i] 表示 i i 连向父亲的这条线的最短长度,选一条边上传,剩下的配对,这时候就要考虑怎么使最长线最短了。
这应该是一个经典的二分问题,二分一个 M i d Mid 表示最长长度,向上传的时候将儿子排序,二分能够向上传的最短长度,然后检验剩下的线配对能否<=Mid。

实现中有几个细节需要注意:

  • 根节点不能向上传,直接检验。
  • 如果 i i 的儿子为偶数个,那么可以不向上传而直接让儿子配对,提前检验。
  • 如果要上传,儿子为偶数个,那么必须留下最大的一个儿子单独成线不配对(这样和上面一种情况用线数相同),剩下的部分同奇数,二分上传哪一个,然后剩下的配对。
  • 配对的检验可以直接最大的和最小的依次配对,正确性比较显然。
  • 也可以不二分上传哪一个,可以用set,将最大的和能够配对的尽量大的配对(upper_bound-1),然后删除,直到最后只剩一个就是上传的最小的长度。

Code:

#include<bits/stdc++.h>
#define maxn 10005
using namespace std;
int n,deg[maxn],f[maxn],g[maxn],cnt,Mid;
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
inline void line(int x,int y){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y;}
bool check(int x){
	for(int l=1,r=cnt;l<r;l++,r--){
		l==x&&l++,r==x&&r--;
		if(l<r&&g[l]+g[r]>Mid) return 0;
	}
	return 1;
}
bool dfs(int u,int ff){
	for(int i=fir[u];i;i=nxt[i]) if(to[i]!=ff&&!dfs(to[i],u)) return 0;
	cnt=0;
	for(int i=fir[u];i;i=nxt[i]) if(to[i]!=ff) g[++cnt]=f[to[i]];
	sort(g+1,g+1+cnt);
	if(u==1) return check(0);
	if(!(cnt&1)){
		if(check(0)) {f[u]=1;return 1;}
		cnt--;
	}
	int l=1,r=cnt+1,mid;
	while(l<r){
		mid=(l+r)>>1;
		if(check(mid)) r=mid;//if(g[mid]<Mid&&check(mid)) is wrong.
		else l=mid+1;
	}
	if(l==cnt+1) return 0;
	else return (f[u]=g[l]+1)<=Mid?1:0;
}
int main()
{
	scanf("%d",&n);
	for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),line(x,y),line(y,x),deg[x]++,deg[y]++;
	int sum=1;
	for(int i=1;i<=n;i++) sum+=(deg[i]-1)>>1;
	int l=1,r=n-1;
	while(l<r){
		Mid=(l+r)>>1;
		if(!dfs(1,0)) l=Mid+1;
		else r=Mid;
	}
	printf("%d %d\n",sum,l);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/102564783
今日推荐