设为首页 加入收藏

TOP

hdu5242 上海邀请赛 优先队列+贪心
2015-11-21 01:00:24 来源: 作者: 【 】 浏览:3
Tags:hdu5242 上海 邀请赛 优先 队列 贪心

题意是给你一棵树 n个点 n-1条边 起点是1 每个点都有权值 每次能从根节点走到叶子节点 经行k次游戏 每次都是从1开始 拿过的点的权值不能拿第二次 问最大权值和;

开始看到题时也没想到什么方法 就按照常规的来 结果超时了 试着优化了好多次 最后过了 百度题解说是树链剖分 醉了 还没学!!!

?

说说我的做法吧 map【i】=a表示i节点的跟节点为a节点 从所有叶子节点开始入队(有点队列里有三个变量 分别是节点编号 权值 深度 优先级看代码 里面有点贪心的意思) 每次走根节点 如果根节点没走过 则走它 并把该店权值变为0 否则直接跳到1这个节点(如果一个个跳可能会超时)再入队 当出队的编号为1时并且拿的个数小于游戏次数 则拿 否则结束 在跑深度的时候有个优化 开始没有超时了 如果该节点深度已知了 则以后的根节点就不用跑了!!! 具体看代码吧

?

?

#include
  
   
#include
   
     #include
    
      #include
      
      using namespace std
      ; int map
      [100010
      ],mark
      [100010
      ]; int Deep
      [100010
      ]; __int64 num
      [100010
      ]; struct node
       { __int64 value
      ; int ii
      ; int deep
      ; bool operator < (const node
      & x
      ) const { return deep
      <x
      .deep
      ||(deep
      ==x
      .deep
      &&value
      <x
      .value
      ); } }a
      ; int main() { int T
      ,i
      ,j
      ,n
      ,k
      ,r
      =1
      ; scanf
      ("%d"
      ,&T
      ); while(T
      --) { scanf
      ("%d%d"
      ,&n
      ,&k
      ); for(i
      =1
      ;i
      <=n
      ;i
      ++) { scanf
      ("%I64d"
      ,&num
      [i
      ]); } memset
      (mark
      ,0
      ,sizeof(mark
      )); for(i
      =1
      ;i
      <n
      ;i
      ++) { int x
      ,y
      ; scanf
      ("%d%d"
      ,&x
      ,&y
      ); mark
      [x
      ]=1
      ; map
      [y
      ]=x
      ; } priority_queue
      <node
      >Q
      ; memset
      (Deep
      ,0
      ,sizeof(Deep
      )); for(i
      =1
      ;i
      <=n
      ;i
      ++) { if(mark
      [i
      ]==0
      ) { int x
      =map
      [i
      ]; int d
      =1
      ; while(x
      !=1
      ) { if(Deep
      [x
      ]>0
      ) {d
      +=Deep
      [x
      ];break;} x
      =map
      [x
      ]; d
      ++; } x
      =i
      ; while(x
      !=1
      ) { if(Deep
      [x
      ]>0
      ) break; Deep
      [x
      ]=d
      ; x
      =map
      [x
      ]; d
      --; } a
      .deep
      =Deep
      [i
      ]; a
      .value
      =num
      [i
      ]; a
      .ii
      =i
      ; Q
      .push
      (a
      ); } } //for(i=1;i<=n;i++) //printf("%d ^^^ %d\n",i,Deep[i]); 
       __int64 sum
      =0
      ; int cont
      =0
      ; while(!Q
      .empty
      ()) { a
      =Q
      .top
      (); Q
      .pop
      (); int x
      =map
      [a
      .ii
      ]; /*while(num[x]==0&&x!=1) { x=map[x]; }*/
       if(a
      .ii
      ==1
      ) { a
      .value
      +=num
      [1
      ]; num
      [1
      ]=0
      ; sum
      +=a
      .value
      ; cont
      ++; if(cont
      >=k
      ) break; } else { if(num
      [x
      ]==0
      ) { a
      .ii
      =1
      ; a
      .deep
      =0
      ; } else { a
      .ii
      =x
      ; a
      .deep
      =Deep
      [x
      ]; a
      .value
      +=num
      [x
      ]; num
      [x
      ]=0
      ; } Q
      .push
      (a
      ); } } printf
      ("Case #%d: %I64d\n"
      ,r
      ++,sum
      ); } return 0
      ; }
     
    
   
  

?

?

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU2149 Public Sale(巴什博奕) 下一篇hdu3388Coprime 二分+容斥原理

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: