loj2071 「JSOI2016」最佳团体

分数规划+树形依赖背包orz

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n, k, s[2505], p[2505], uu, dfn[2505], idx, fff[2505], fan[2505], hea[2505];
int cnt;
double dp[2505][2505];
struct Edge{
	int too, nxt;
}edge[5005];
void add_edge(int fro, int too){
	edge[++cnt].nxt = hea[fro];
	edge[cnt].too = too;
	hea[fro] = cnt;
}
void dfs(int x, int f){
	dfn[x] = ++idx;
	fan[idx] = x;
	for(int i=hea[x]; i; i=edge[i].nxt){
		int t=edge[i].too;
		if(t!=f)	dfs(t, x);
	}
	fff[dfn[x]] = idx + 1;
}
bool chk(double mid){
	memset(dp, 0xcf, sizeof(dp));
	dp[1][0] = 0;
	for(int i=1; i<=n+1; i++)
		for(int j=0; j<=k; j++){
			dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j]+p[fan[i]]-mid*s[fan[i]]);
			dp[fff[i]][j] = max(dp[i][j], dp[fff[i]][j]);
		}
	return dp[n+2][k]>=0;
}
int main(){
	cin>>k>>n;
	k++;
	for(int i=1; i<=n; i++){
		scanf("%d %d %d", &s[i], &p[i], &uu);
		add_edge(i, uu);
		add_edge(uu, i);
	}
	dfs(0, 0);
	double l=0.0, r=1e4, mid, re;
	while(fabs(r-l)>=1e-6){
		mid = (l + r) / 2.0;
		if(chk(mid))	re = mid, l = mid;
		else	r = mid;
	}
	printf("%.3f
", re);
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/9046472.html