BZOJ 2103/3302/2447 消防站 树的重心【DFS】【TreeDP】
2103: Fire 消防站
Time Limit: 30 Sec Memory Limit: 259 MBSubmit: 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
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
【样例解释】
选取区域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\n",ans); 84 }