[JZOJ5400]: Repulsed (greedy + tree DP)

Title Description

  Small $ w $ in the heart of the flame will be extinguished.
  Simplicity, let's say $ W $ heart is a $ n-1 $ edges, n-$ $ tree nodes.
  Now you want to put some fire extinguishers at each node, each node can put any number.
  Next, each node must be assigned to a strip of at most $ k $ remote fire extinguisher, a fire extinguisher for each assigned to up to $ s $ nodes.
  At least the number of fire extinguishers to make small $ w $ completely give up hope it?


Input Format

  The first row of three integers $ n, s, k $.
  Next, $ n-1 $ lines each represent an integer of two sides.


Output Format

  Integer answer a row


Sample

Sample input:

10 10 3
1 8
2 3
1 5
2 4
1 2
8 9
8 10
5 6
5 7

Sample output:

1


Data range and tips

  For $ 20 \% $ data satisfies $ n \ leqslant 100, k \ leqslant 2 $.
  For another $ 20 \% $ data satisfies $ k = 1 $.
  For another $ 20 \% $ data satisfies $ s = 1 $.
  Data for $ 100 \% $ satisfies $ n \ leqslant 10 ^ 5, k \ leqslant 20, s \ leqslant 10 ^ 9 $.


answer

Consider first greedy, in turn elect the deepest point it has not covered some better, with a heap maintain this Jiuhaola.

But there may be a fire extinguisher intersection great situation.

Consider again $ DP $, set $ G [x] [k] $ denotes $ X $ following distance is the number of $ k $ need extinguisher room, $ F [x] [k] $ denotes $ X $ following distance is $ the excess number of fire extinguishers k $.

First $ G [x] [k] $ to [x] [0] $ matches $ F.

Note also be cross $ LCA $, so $ G [x] [i] $ may also be $ F [x] [ki] $ match, $ G [x] [i] $ and $ F [x] [ki -1] $ match.

Then there is the transfer:

$$F[u][i]=\sum\limits_vF[v][i-1]$$

$$G[u][i]=\sum\limits_vG[v][i+1]$$

Initialization $ F [x] [i] = G [x] [i] = 1 $ can.

When matched with the pointer maintain enough.

Time complexity: $ \ Theta (nk) $.

Expectations score: $ 100 $ points.

Actual score: $ 100 $ points.


Code time

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[200000];
int head[100001],cnt;
int n,s,k;
int f[100001][21],g[100001][21];
bool vis[100001];
int ans,sum;
void add(int x,int y)
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
void dfs(int x)
{
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
	{
		if(vis[e[i].to])continue;
		dfs(e[i].to);
		for(int j=1;j<=k;j++)
		{
			f[x][j]+=f[e[i].to][j-1];
			g[x][j-1]+=g[e[i].to][j];
			g[x][j-1]=min(g[x][j-1],n);
		}
	}
	f[x][0]++;
	if(f[x][k])
	{
		int tmp=(ceil)((double)f[x][k]/s);
		ans+=tmp;
		g[x][k]+=min(tmp*s,n)-f[x][k];
		f[x][k]=0;
	}
	int fail=k;
	for(int i=k;~i;i--)
		while(f[x][i]&&fail>=i)
		{
			int flag=min(f[x][i],g[x][fail]);
			f[x][i]-=flag;g[x][fail]-=flag;
			if(!g[x][fail])fail--;
		}
}
int main()
{
	scanf("%d%d%d",&n,&s,&k);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs(1);
	for(int i=0;i<=k;i++)sum+=f[1][i];
	ans+=(ceil)((double)sum/s);
	printf("%d",ans);
	return 0;
}

rp++

Guess you like

Origin www.cnblogs.com/wzc521/p/11832954.html