ZOJ 3684 Destroy
来源:互联网 发布:嵌入式linux原理 编辑:程序博客网 时间:2024/05/05 06:54
题意: 给你一棵树,树的根是树的中心(到其他点的最远距离最小)。现在你要破坏所有叶子节点到根节点的连通,每条边破坏都需要一定能量。你有一个能量为power的武器,能破坏能量小于等于power的任何路。求最小的power。
思路:先找出中心,然后树形dp求一下这个最小power。找中心也是树形dp,技巧就是fir[u]表示u为根的子树里的点到u的第一远距离,sec[u]第二远,随便先选一个点为根(假设1)dfs一下就能求出。这样预处理好后,再从1开始树形dp,这时候fir[u]表示距离u第一远的距离,sec[u]是第二远,如果u这个点还没被更新过,那么fir和sec的含义依然和原来一样。现在从u到v(注意u已经被更新过了,v还没)。考虑此时如何更新v的fir[v],现在firv[v]已经记录了v子树内的点的最远距离,我们只要知道除去v子树里的点,其他点到v的最远距离,就能更新fir[v]。现在u被更新过了,那么fir[u]表示距离u第一远的距离,sec[u]是第二远。如果fir[v]+d[u][v]==fir[u]那么说明u点的最远点在v子树内,所以我们只能用sec[u]+d[u][v],反之用fir[u]=d[u][v]去更新。最后找出最小的fir[center]。知道中心后再一个dp就好了。找中心的方法好好理解后不会难,本吊语文水平有限,表达能力只能到这了,各位自己意会吧。。。
#include<string.h>#include<stdio.h>#include<algorithm>using namespace std;#define N 10010#define ll long longint n,p[N],eid,fir[N],sec[N];ll dp[N];const ll INF=1ll<<60;struct node{int to,len,pow,next;}e[N<<2];void init(){memset(p,-1,sizeof(p));eid=0;}void insert(int from,int to,int l,int w){e[eid].len=l;e[eid].pow=w;e[eid].to=to;e[eid].next=p[from];p[from]=eid++;}namespace pretreat{void dfs(int u,int pre){int v,newlen;fir[u]=fir[u]=0;for(int i=p[u];i!=-1;i=e[i].next){v=e[i].to;if(v==pre) continue;dfs(v,u);newlen=fir[v]+e[i].len;if(fir[u]<newlen){sec[u]=fir[u];fir[u]=newlen;}else if(sec[u]<newlen){sec[u]=newlen;}}}void DP(int u,int pre){int v;for(int i=p[u];i!=-1;i=e[i].next){v=e[i].to;if(v==pre) continue;if(fir[u]==fir[v]+e[i].len){fir[v]=max(fir[v],sec[u]+e[i].len);sec[v]=max(sec[v],sec[u]+e[i].len);}else{fir[v]=max(fir[v],fir[u]+e[i].len);sec[v]=max(sec[v],fir[u]+e[i].len);}DP(v,u);}}int findCenter(){int center;dfs(1,0);DP(1,0);center=min_element(fir+1,fir+n+1)-fir;return center;}}namespace solve{void dfs(int u,int pre){int v,flag=0;ll power=0;dp[u]=INF;for(int i=p[u];i!=-1;i=e[i].next){v=e[i].to;if(v==pre) continue;dfs(v,u);power=max(power,min(dp[v],(ll)e[i].pow));flag=1;}if(flag) dp[u]=power;}ll getMinPower(int center){dfs(center,0);return dp[center];}}int main(){using namespace pretreat;using namespace solve;int x,y,l,w,center;while(~scanf("%d",&n)){init();for(int i=0;i<n-1;i++){scanf("%d %d %d %d",&x,&y,&l,&w);insert(x,y,l,w);insert(y,x,l,w);}center=findCenter();//printf("%d\n",center);printf("%lld\n",getMinPower(center));}return 0;}
- ZOJ 3684 Destroy
- ZOJ 3684 Destroy
- ZOJ 3684 Destroy 树的直径+二分
- ZOJ 3684 Destroy 树的中心
- poj 3684 Destroy
- Destroy
- AbstractApplicationContext -> destroy()
- WebView.destroy()
- angularjs-$destroy
- Destroy Walls
- Destroy大小写敏感吗?
- DisposableBean destroy-method
- Spring中的destroy-method
- openssl init destroy
- 配置destroy-method
- unity3d Object.Destroy 销毁
- Destroy WebView in Android
- 【源码】Object.Destroy 销毁
- 巧用WORD进行字符与Unicode字符的转换
- Android Intent分享到腾讯微博,信息,新浪微博等等,的实现方式
- java和js中如何操作cookie
- js继承有5种实现方式
- [转]概率主题模型简介 Introduction to Probabilistic Topic Models
- ZOJ 3684 Destroy
- CareerCup 14.6
- json linux c parser
- window激活
- 从程序员到项目经理(9):程序员加油站 -- 再牛也要合群
- STL中list用法详解
- 「学习笔记——Python」《The Python Tutorial》学习结束语
- setjmp and longjmp
- s3c2410_gpio_cfgpin等内核导出函数