zoukankan      html  css  js  c++  java
  • hdu 4679 Terrorist’s destroy 树形DP

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4679

    题意:给定一颗树,每条边有一个权值w,问切掉哪条边之后,分成的两颗树的较大的直径*切掉边的权值最小?如果存在多条边使得结果相同,输出边id最小的

    思路:

    dept一次找出最深的节点,之后以最深的节点出发(rt1)dept找到树的直径(即找到rt2);将路径保存在f[]中;

    之后分别从rt1/rt2进行深搜,找到以一个节点为根的树的直径,这样在每次dfs之后,可以求出每条边的一边的最值,这样两次取max之后就求出了切掉该边之后得到的结果

    注:

    如果改变在整棵树的直径上,需要取出以该棵树为根的树的直径maxn[0][v];否则就直接取整棵树的直径即可;

    在dfs递推出以某根为子树的直径时,可能直径不过根节点所以要将子子树的直径递推到子树上;

      1 #include<bits/stdc++.h>
      2 #pragma comment(linker, "/STACK:1024000000,1024000000") //加栈
      3 using namespace std;
      4 #define rep0(i,l,r) for(int i = (l);i < (r);i++)
      5 #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
      6 #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
      7 #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
      8 #define MS0(a) memset(a,0,sizeof(a))
      9 #define MS1(a) memset(a,-1,sizeof(a))
     10 #define MSi(a) memset(a,0x3f,sizeof(a))
     11 #define inf 0x3f3f3f3f
     12 #define lson l, m, rt << 1
     13 #define rson m+1, r, rt << 1|1
     14 typedef pair<int,int> PII;
     15 #define A first
     16 #define B second
     17 #define MK make_pair
     18 typedef long long ll;
     19 typedef unsigned int uint;
     20 template<typename T>
     21 void read1(T &m)
     22 {
     23     T x=0,f=1;char ch=getchar();
     24     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     25     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     26     m = x*f;
     27 }
     28 template<typename T>
     29 void read2(T &a,T &b){read1(a);read1(b);}
     30 template<typename T>
     31 void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
     32 template<typename T>
     33 void out(T a)
     34 {
     35     if(a>9) out(a/10);
     36     putchar(a%10+'0');
     37 }
     38 #define N 100007
     39 int head[N<<1],tot;
     40 struct edge{
     41     int to,w,id,Next;
     42 }e[N<<1];
     43 void ins(int a,int b,int w,int id)
     44 {
     45     e[++tot].Next = head[a];
     46     e[tot].to = b;
     47     e[tot].w = w;
     48     e[tot].id = id;
     49     head[a] = tot;
     50 }
     51 int dep[N],p[N];
     52 void dept(int u,int pre)
     53 {
     54     p[u] = pre;
     55     dep[u] = dep[pre] + 1;
     56     for(int id = head[u];id;id = e[id].Next){
     57         int v = e[id].to;
     58         if(v == pre) continue;
     59         dept(v,u);
     60     }
     61 }
     62 int f[N],maxlen;//树的直径
     63 int aux[N];
     64 int maxn[3][N];
     65 void dfs(int u,int pre)
     66 {
     67     maxn[0][u] = maxn[1][u] = maxn[2][u] = 0;
     68     for(int id = head[u];id;id = e[id].Next){
     69         int v = e[id].to;
     70         if(v == pre) continue;
     71         dfs(v,u);
     72         if(maxn[1][u] <= maxn[1][v]+1){
     73             maxn[2][u] = maxn[1][u];
     74             maxn[1][u] = maxn[1][v]+1;
     75         }else if(maxn[2][u] < maxn[1][v]+1)
     76             maxn[2][u] = maxn[1][v]+1;
     77         if(maxn[0][u] < maxn[0][v])    //**可能树的直径不过根节点;
     78             maxn[0][u] = maxn[0][v];
     79     }
     80     maxn[0][u] = max(maxn[0][u],maxn[1][u] + maxn[2][u]);  //以u为根的子树的直径
     81 }
     82 void solve(int u,int pre)
     83 {
     84     for(int id = head[u];id;id = e[id].Next){
     85         int v = e[id].to, w = e[id].w;
     86         if(v == pre) continue;
     87         if(f[u] && f[v]){ //边在直径上
     88             aux[e[id].id] = max(aux[e[id].id],w*maxn[0][v]);
     89         }else{
     90             aux[e[id].id] = max(aux[e[id].id],w*maxlen);
     91         }
     92         solve(v,u);
     93     }
     94 }
     95 int main()
     96 {
     97     //freopen("data.txt","r",stdin);
     98     //freopen("out.txt","w",stdout);
     99     int kase = 1,T,n;
    100     read1(T);
    101     while(T--){
    102         MS0(head);tot = 0;
    103         MS0(f);
    104         read1(n);
    105         rep0(i,1,n){
    106             int u,v,w;
    107             read3(u,v,w);
    108             ins(u,v,w,i);ins(v,u,w,i);
    109         }
    110         dep[0] = 0;
    111         dept(1,0);
    112         int rt1 ,rt2 ,d = 0;
    113         rep1(i,1,n) if(d < dep[i]) d = dep[i],rt1 = i;
    114         dept(rt1,0);
    115         d = 0;
    116         rep1(i,1,n) if(d < dep[i]) d = dep[i],rt2 = i;
    117         maxlen = d-1; //求出树的直径;以及两端的节点标号
    118         int index = rt2;
    119         while(index){
    120             f[index] = 1;
    121             index = p[index];   //从树直径的终点递推到起点
    122         }
    123         MS0(aux);
    124         dfs(rt1,-1);
    125         solve(rt1,0);
    126         dfs(rt2,-1);
    127         solve(rt2,0);
    128         int ans = inf;
    129         rep0(i,1,n){
    130             if(ans > aux[i]) ans = aux[i],index = i;
    131         }
    132         printf("Case #%d: %d
    ",kase++,index);
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    每日总结:DIV弹层遮盖、DIV设置透明背景色、JS调用SharePoint 中的SP.UI.ModalDialog弹出遮盖层显示
    八、WinForm客户端的配置与使用
    11.1 使用框架应具备哪些知识或技能?
    五、框架的结构
    11.2 如何取得汉字的拼音或者拼音首字母缩写?
    九、IBeamMDAA的Web客户端的配置与使用
    六、框架的应用服务器配置
    十、IBeamUtility的使用
    七、IBeamMDAA在IIS宿主服务器的配置
    三、框架的目标与解决的问题
  • 原文地址:https://www.cnblogs.com/hxer/p/5656411.html
Copyright © 2011-2022 走看看