[POI2013]LUK-Triumphal arch

题目链接

此题的答案k具有可二分性

那么我们可以二分答案k,然后跑一个树形DP

\(dp[i]\)表示到节点\(i\)时需要再多染色的点数

那么有\(dp[i]=\max(\sum_{fa[j]=i} (dp[j]+1)-k,0)\)

\(dp[1]=0\)则答案k可行

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;

const int MAXN=1e5+5;

int n,np;
int h[MAXN],f[MAXN];
struct rpg{
	int li,nx;
}a[MAXN<<1];

void add(int ls,int nx)
{
	a[++np]=(rpg){h[ls],nx};h[ls]=np;
	a[++np]=(rpg){h[nx],ls};h[nx]=np;
}

void dfs(int x,int fa,int mid)
{
	int sum=0;f[x]=0;
	for(int i=h[x];i;i=a[i].li){
		if(a[i].nx!=fa){
			dfs(a[i].nx,x,mid);
			sum+=f[a[i].nx]+1;
		}
	}f[x]=max(sum-mid,0);
	return;
}

bool check(int mid)
{
	int sum=0;f[1]=0;
	for(int i=h[1];i;i=a[i].li){
		dfs(a[i].nx,1,mid);
		sum+=f[a[i].nx]+1;
	}f[1]=max(sum-mid,0);
	return !f[1];
}

int main()
{
	scanf("%d",&n);for(int i=1;i<n;++i){int x,y;scanf("%d%d",&x,&y),add(x,y);}
	int l=0,r=n;
	while(l<r){
		int mid=l+r>>1;
		if(check(mid)) r=mid;
		else l=mid+1;
	}printf("%d\n",l);
	return 0;
}
posted @ 2018-09-10 16:18  A·H  阅读(191)  评论(0编辑  收藏  举报