Information Disturbing(树形dp)

http://acm.hdu.edu.cn/showproblem.php?pid=3586


思路:

开始照着重建道路跑树形背包了。发现并不行。

这题只要1维就够了。

dp[u]以u为根的子树切断了和叶子所有的关系的价值和。

然后将答案转化成二分判定当前dp[1]是否>=m

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
struct Edge{
   LL to,val;
};
vector<Edge>g[maxn];
LL dp[maxn];
void dfs(LL u,LL fa,LL li){
     dp[u]=0;
     bool flag=1;
     for(LL i=0;i<g[u].size();i++){
         LL v=g[u][i].to;LL cost=g[u][i].val;
         if(v==fa) continue;
         dfs(v,u,li);
         flag=0;
         if(cost>li){
            dp[u]+=dp[v];
         }
         else{
            dp[u]+=min(dp[v],cost);
         }
     }
     if(flag) dp[u]=1e13;
}
int main(void){
   cin.tie(0);std::ios::sync_with_stdio(false);
   LL n,m;
   while(cin>>n>>m&&n&&m){
      for(LL i=0;i<maxn;i++){
         g[i].clear();
      }
      for(LL i=1;i<n;i++){
          LL u,v,val;cin>>u>>v>>val;
          g[u].push_back({v,val});
          g[v].push_back({u,val});
      }
      LL l=1;LL r=1e13;
      while(l<r){
           LL mid=(l+r)>>1;
           dfs(1,0,mid);
           if(dp[1]<=m) r=mid;
           else l=mid+1;
      }
      if(l==1e13){
        cout<<"-1"<<"\n";
      }
      else{
        cout<<l<<"\n";
      }
   }
   return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Python3代码实现: ```python class Animation: def animate(self, speed: int, init: str) -> List[str]: # 将初始状态转换为列表 particles = list(init) # 记录每个时间步的状态 result = [] # 当前时间步的状态 current_state = init while True: # 记录当前时间步状态 result.append(current_state.replace('R', 'X').replace('L', 'X')) # 用于记录下一时间步状态的列表 next_state = ['.' for _ in range(len(particles))] # 标记每个方向的粒子是否已经到达边界 left_reach_edge, right_reach_edge = False, False # 处理向右移动的粒子 for i in range(len(particles)): if particles[i] == 'R': # 粒子向右移动 next_pos = i + speed # 判断粒子是否到达边界 if next_pos >= len(particles): right_reach_edge = True else: # 判断下一位置是否有粒子 if next_state[next_pos] != 'X': next_state[next_pos] = 'R' # 处理向左移动的粒子 for i in range(len(particles) - 1, -1, -1): if particles[i] == 'L': # 粒子向左移动 next_pos = i - speed # 判断粒子是否到达边界 if next_pos < 0: left_reach_edge = True else: # 判断下一位置是否有粒子 if next_state[next_pos] != 'X': next_state[next_pos] = 'L' # 更新当前时间步状态 current_state = ''.join(next_state) # 判断是否所有粒子都已经离开了 if left_reach_edge and right_reach_edge: result.append(current_state.replace('R', '.').replace('L', '.')) break # 更新粒子位置列表 particles = next_state return result ``` 我们定义了一个名为Animation的类,其中包含一个animate方法,用于实现题目所需的功能。在animate方法内部,我们首先将初始状态转换为列表,然后记录每个时间步的状态,并将其存储在result列表中。接下来,我们使用两个for循环分别处理向右移动和向左移动的粒子。对于向右移动的粒子,我们计算它们下一时刻的位置,并将其存储在next_state列表中。如果下一位置没有粒子,则将该粒子标记为向右移动。对于向左移动的粒子,我们采用类似的方法处理。最后,我们更新当前时间步状态并判断是否所有粒子都已经离开了,如果是,我们将最后一个时间步状态添加到结果列表中,并退出循环。最后,我们返回result列表作为最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值