zoukankan      html  css  js  c++  java
  • BZOJ 2103/3302/2447 消防站 树的重心【DFS】【TreeDP】

    2103: Fire 消防站

    Time Limit: 30 Sec  Memory Limit: 259 MB
    Submit: 157  Solved: 116
    [Submit][Status][Discuss]

    Description

    Input

    共N+1行。 第一行有一个正整数N,表示区域的个数。 接下来有N-1行,每行两个整数u、v,表述区域u和区域v之间有一条道路。 最后一行有N个正整数,第i个正整数表示区域i的权值W(i)。

    Output

    包含一个正整数,为最小的S(x, y)的值。

    Sample Input

    5
    1 2
    1 3
    3 4
    3 5
    5 7 6 5 4

    Sample Output

    14
    【样例解释】
    选取区域2和区域3。
    【数据规模和约定】
    用H表示距离区域1最远结点的距离,即d(1, u)的最大值。
    对于30%的数据满足:2 ≤ N ≤ 5000、H ≤ 30
    对于70%的数据满足:2 ≤ N ≤ 50000、H ≤ 30
    对于100%的数据满足:2 ≤ N ≤ 50000、H ≤ 70、W(i) ≤ 100
     
    http://blog.csdn.net/braketbn/article/details/51055715
     1 #pragma GCC optimize(2)
     2 #pragma G++ optimize(2)
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 
     9 #define ll long long 
    10 #define N 50007
    11 #define inf 1000000007
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    17     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 
    21 int n,cut;
    22 int fa[N],dep[N],mx1[N],mx2[N];
    23 ll sum[N],res[N],ans;
    24 int cnt,hed[N],rea[N<<1],nxt[N<<1];
    25 
    26 void add(int u,int v)
    27 {
    28     nxt[++cnt]=hed[u];
    29     hed[u]=cnt;
    30     rea[cnt]=v;
    31 }
    32 void dfs(int u)
    33 {
    34     for (int i=hed[u];~i;i=nxt[i])
    35     {
    36         int v=rea[i];
    37         if(v==fa[u])continue;
    38         dep[v]=dep[u]+1,fa[v]=u;
    39         dfs(v);
    40         sum[u]+=sum[v];
    41         res[u]+=res[v]+sum[v];
    42         if(!mx1[u]||sum[v]>sum[mx1[u]])mx2[u]=mx1[u],mx1[u]=v;
    43         else if(!mx2[u]||sum[v]>sum[mx2[u]])mx2[u]=v;
    44     }
    45 }
    46 void find_center(ll &ret,int rt,int x,ll k,int jd)
    47 {
    48     ret=min(ret,k);
    49     int v=mx1[x];
    50     if(v==cut||sum[mx2[x]]>sum[mx1[x]])v=mx2[x];
    51     if(!v)return;
    52     find_center(ret,rt,v,k+sum[rt]-2*sum[v],jd);
    53 }
    54 void solve(int u)
    55 {
    56     for (int i=hed[u];~i;i=nxt[i])
    57     {
    58         int v=rea[i];cut=rea[i];
    59         if(v==fa[u])continue;
    60         ll gx=inf,gy=inf;
    61         for (int j=u;j;j=fa[j])sum[j]-=sum[cut];
    62         find_center(gx,1,1,res[1]-res[cut]-dep[cut]*sum[cut],u);
    63         find_center(gy,cut,cut,res[cut],u);
    64         ans=min(ans,gx+gy);
    65         for (int j=u;j;j=fa[j])sum[j]+=sum[cut];
    66         solve(v);
    67     }
    68 }
    69 int main()
    70 {
    71     n=read();
    72     memset(hed,-1,sizeof(hed));
    73     for (int i=1;i<n;i++)
    74     {
    75         int x=read(),y=read();
    76         add(x,y),add(y,x);
    77     }
    78     for (int i=1;i<=n;i++)
    79         sum[i]=read();
    80     ans=inf;
    81     dfs(1);
    82     solve(1);
    83     printf("%lld
    ",ans);
    84 }
  • 相关阅读:
    hihocoder_offer收割编程练习赛53_2hiho字符串3
    hihocoder_offer收割编程练习赛53_1继承顺位
    网易招聘笔试题--牛牛的背包问题
    EJB3.0快速入门
    MyEclipse的常用快捷操作----非常实用!!!
    Spring2.5零散笔记
    Hibernate零散笔记
    一个问题引发的OOA&OOD讨论.
    如何使用JUnit进行单元测试
    Log4j自学笔记
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8503937.html
Copyright © 2011-2022 走看看