hdu 5854K-th value (2016多校第九场1011) 树形dp

来源:互联网 发布:知乎 爬虫 加载 编辑:程序博客网 时间:2024/05/18 16:57

我们二分一下答案,然后发现如果小于等于答案的个数x,剩下的是y个那么一定满足:x>(x+y)/k也就是(k-1)*x-y>0所以我们只需要把小于等于答案的变成k-1,其他的变成-1跑一遍树形dp即可。

#include<cstring>#include<cstdio>#include<algorithm>#include<iostream>#include<vector>using namespace std;const int maxn=100004;struct pi{    int a,b,c;}pp[maxn];int k,l,r;typedef pair<int,int>p1;vector<p1>g[maxn];int dp[maxn][52];int ans;void dfs(int u,int pa){    dp[u][0]=0;    for(int i=1;i<=r;i++) dp[u][i]=-1000000000;    for(p1 v:g[u]){        if(v.first!=pa){            dfs(v.first,u);            if(ans) return;            for(int i=0;i<r;i++){                for(int j=max(0,l-i-1);j+i+1<=r;j++){                    if(dp[u][j]+dp[v.first][i]+v.second>0){                        ans=1;                        return;                    }                }            }            for(int i=0;i<r;i++){                dp[u][i+1]=max(dp[u][i+1],dp[v.first][i]+v.second);            }        }    }}int main(){    int t,n;    cin>>t;    while(t--){        scanf("%d",&n);        for(int i=1;i<n;i++) scanf("%d%d%d",&pp[i].a,&pp[i].b,&pp[i].c);        scanf("%d%d%d",&k,&l,&r);        int le=1,ri=1000000000;        while (le<=ri) {            int mid=(le+ri)/2;            for(int i=1;i<=n;i++) g[i].clear();            for(int i=1;i<n;i++){                if(pp[i].c>mid){                    g[pp[i].a].push_back(make_pair(pp[i].b,-1));                    g[pp[i].b].push_back(make_pair(pp[i].a,-1));                }                else{                    g[pp[i].a].push_back(make_pair(pp[i].b,k-1));                    g[pp[i].b].push_back(make_pair(pp[i].a,k-1));                }            }            ans=0;            dfs(1,-1);            if(ans) ri=mid-1;            else le=mid+1;        }        if(le>1000000000) printf("-1\n");        else printf("%d\n",le);    }}


0 0
原创粉丝点击