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