| input | output |
|---|---|
6 3 1 2 2 2 2 1 1 2 1 4 |
50.00000000 |
题意:
输入 n 个人,3是表示有多少时间让编号1 的人召集人马。
然后按2到n 的编号 输入pi 和ti。分别是那个人直接 领主,和召集自己本部的人所需的时间。 编号1 是大领主 。 假设 每个领主都只能在 直属下属 有≥x% 的人召齐了人马才可以开始招自己的人。 问x最大是多少,可以让大领主在 t 的时间内 召齐自己的人出发打仗。
做法:
二分x,判断下这个x能否在所需时间内召齐人马。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <vector>
long long p[10010],t[10010];
long long nowt[10010];
long long pai[100010];
double x;
long long sum_t;
vector <long long >son[10010];
void dfs(long long nod)
{
if(son[nod].size()==0)
{
nowt[nod]=t[nod];
return ;
}
for(long long i=0;i<son[nod].size();i++)
dfs(son[nod][i]);
long long need=ceil(1.0*son[nod].size()*x/100.0);//找到所需的最少人数是多少
for(long long i=0;i<son[nod].size();i++)
pai[i]=nowt[son[nod][i]];
sort(pai,pai+son[nod].size());
long long ret;
if(need==0)
ret=0;
else
ret=pai[need-1]; //手下的人中,花费最长时间的那个人
nowt[nod]=ret+t[nod];
}
long long deal()
{
dfs(1);
if(nowt[1]>sum_t)
return 0;
else
return 1;
}
int main()
{
long long n;
while(scanf("%I64d%I64d",&n,&sum_t)!=EOF)
{
for(long long i=1;i<=n;i++)
son[i].clear();
for(long long i=2;i<=n;i++)
{
scanf("%I64d%I64d",p+i,t+i);
son[p[i]].push_back(i);
}
double l=0,r=100;//
double mid;
while(abs(r-l)>0.0001)
{
mid=(l+r)/2.0;
x=mid;
if(deal()==0)//所需时间大于 sum_t
r=mid;
else
l=mid;
}
printf("%.7lf\n",l);
}
return 0;
}
URAL 1822. Hugo II's War 树的结构+二分
原文:http://blog.csdn.net/u013532224/article/details/44315513