您的位置:首页 > 其它

Codeforces 682C Alyona and the Tree DP

2017-04-06 20:54 537 查看
点击打开链接

题意:n个结点带权树,边可以为负,n<=1e5,要求对每个v:满足若u为v的子孙,dist(u,v)<=a[u],op:每次可以删除leaf,问最小操作次数 

令dp[u]为以u开头(往祖先走)的最大子串和,(或者递归时保存最小的dist[1,v],dist[u,v]=dist[1,u]-dist[1,v]]),若dp[u]>a[u] 则u是肯定要删除滴.

op每次只能删除leaf,当u变为leaf 删除的为u的子树大小,从上往下删除保证不重复删 

dp[u]=max(dp[u],dp[v]+w)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=2e5+20;
const ll inf=2e15;
int n,a
,vis
,sz
;
ll dp
;
int ans;
vector<ii> e
;
void dfs(int u)
{
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].first,w=e[u][i].second;
dp[v]=max(dp[v],w+dp[u]);//祖先的dp值要先确定
dfs(v);
sz[u]+=sz[v];
}
}
void dfs_del(int u)
{
if(dp[u]>a[u])
{
ans+=sz[u];
return;
}
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].first;
dfs_del(v);
}
}
int main()
{
while(cin>>n)
{
ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),dp[i]=0,e[i].clear(),sz[i]=1;
int u,w;
for(int i=2;i<=n;i++)
{
scanf("%d%d",&u,&w);
e[u].push_back(ii(i,w));
}
dfs(1);//calc
dfs_del(1);
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: