当前位置:   article > 正文

【算法每日一练】动态规划,图论(换根dp)会议 ,医院设置

【算法每日一练】动态规划,图论(换根dp)会议 ,医院设置

目录

        

题目: 会议

 思路:

题目:医院设置 

思路:


        

                

        

题目: 会议

         

 思路:

首先,阅读题目可以看出来,这道题目实际上就是求树的重心

树的重心

定义:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,达到的效果是生成的多棵树尽可能平衡。

举个例子:

我们不妨设置d[i]表示以此点为根的所有点总距离和,cnt[i]表示以此为根的节点数

我们首先知道d[1]=16,cnt[1]=10我们来看d[2]应该怎么求,我们发现相对于d[1]来说,如果设2为最佳点,2,5,6其距离-1,剩下的1,4,3,7,8,9,10到其距离+1。

故:d[2]=d[1] - 3 + 7 =20

其中3是子根2对应的节点数cnt[2],7是1为子根对应的节点数cnt[1]-cnt[2]

得:d[i]=d[fa]-cnt[i]+(cnt[1]-cnt[i])

那么只需要先dfs求出来d[1]和每个点的cnt[i]。然后就可以进行dp最终求出所有点的d[i]。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=50005;
  4. int minn=0x3f3f3f3f,ans,n,d[N],cnt[N];
  5. vector<int>ve[N];
  6. void dfs(int u,int fa,int len){//一定别走fa回去
  7. cnt[u]++;//先加上自己
  8. for(int i=0;i<ve[u].size();i++){
  9. int v=ve[u][i];
  10. if(v==fa)continue;
  11. dfs(v,u,len+1);//先求孩子的cnt,之后求自己cnt
  12. cnt[u]+=cnt[v];
  13. }
  14. d[1]+=len;//最后求d[1]
  15. }
  16. void dp(int u,int fa){
  17. for(int i=0;i<ve[u].size();i++){
  18. int v=ve[u][i];
  19. if(v==fa)continue;
  20. d[v]=d[u]-2*cnt[v]+cnt[1];
  21. dp(v,u);//这里对自己进行转移更新,再对孩子的更新
  22. }
  23. }
  24. int main(){
  25. cin>>n;int a,b;
  26. for(int i=1;i<n;i++){
  27. cin>>a>>b;
  28. ve[a].push_back(b);
  29. ve[b].push_back(a);
  30. }
  31. dfs(1,0,0);
  32. dp(1,0);
  33. for(int i=1;i<=n;i++){
  34. if(d[i]<minn)
  35. minn=d[i],ans=i;
  36. }
  37. cout<<ans<<" "<<minn;
  38. }

上面我打注释的地方一定要理解 

        

        

题目:医院设置 

思路:

还是一道求树的重心题。不过是每个点都有一个权值。那么把权值当成“另一个世界的节点数”就好了。然后不断求cnt,之后dp就行。 

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=500;
  4. int ans=0x3f3f3f3f,n,d[N],cnt[N],w[N];
  5. vector<int>ve[N];
  6. void dfs(int u,int fa,int len){
  7. cnt[u]=w[u];//这里还是先加自己
  8. for(int i=0;i<ve[u].size();i++){
  9. int v=ve[u][i];
  10. if(v==fa)continue;
  11. dfs(v,u,len+1);
  12. cnt[u]+=cnt[v];
  13. }
  14. d[1]+=len*w[u];//更新d[1]也要变一下
  15. }
  16. void dp(int u,int fa){
  17. for(int i=0;i<ve[u].size();i++){
  18. int v=ve[u][i];
  19. if(v==fa)continue;
  20. d[v]=d[u]+cnt[1]-cnt[v]*2;
  21. dp(v,u);
  22. }
  23. ans=min(ans,d[u]);
  24. }
  25. int main(){
  26. cin>>n;int c,a,b;
  27. for(int i=1;i<=n;i++){
  28. cin>>c>>a>>b;
  29. w[i]=c;//注意输入方式
  30. if(a)ve[i].push_back(a),ve[a].push_back(i);
  31. if(b)ve[i].push_back(b),ve[b].push_back(i);
  32. }
  33. dfs(1,0,0);
  34. dp(1,0);
  35. cout<<ans;
  36. }

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/594921
推荐阅读
相关标签
  

闽ICP备14008679号