[树Dfs][Usaco2010 Mar]gather奶牛大集会
2013-10-15 21:43
253 查看
题目大意:
Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会。当然,她会选择最方便的地点来举办这次集会。每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场。道路i连接农场A_i和B_i(1 <= A_i <=N; 1 <= B_i <= N),长度为L_i(1 <= L_i <= 1,000)。集会可以在N个农场中的任意一个举行。另外,每个牛棚中居住者C_i(0 <= C_i <= 1,000)只奶牛。在选择集会的地点的时候,Bessie希望最大化方便的程度(也就是最小化不方便程度)。比如选择第X个农场作为集会地点,它的不方便程度是其它牛棚中每只奶牛去参加集会所走的路程之和,(比如,农场i到达农场X的距离是20,那么总路程就是C_i*20)。帮助Bessie找出最方便的地点来举行大集会。考虑一个由五个农场组成的国家,分别由长度各异的道路连接起来。在所有农场中,3号和4号没有奶牛居住。
solution:
1、将树看成以1为根的一棵有根树。
2、用一个s
记录该节点以下的牛的个数。
3、用一个a
表示该节点为聚会地点时,奶牛们的不方便程度。
那么有:
s[ i ]=v[i]+s[ s(i) ];
a[ i ]+=a[ son(i) ]+s[son(i)]*w
a[ i ]+=(total - s[ i ])*w+(a[father(i) ]-a[ i ]-s[v]*w)
其中v[i] 表示该点的牛数目,total 表示总的牛数量,w 表示 father(i) 到i点的距离。
这样,进行两次DFS,第一次DFS则要得到s[]的值还有以这棵树来看时候的a[]值,
这个时候a[]值仅为a[ son(i) ] + s[ son(i) ]* w,
不算包括父亲在内的另一部分子树的不满意度,第二次DFS则要计算a[],
需要两次DFS的原因是,必须要用一个节点的不满意度已经求出,才能求出这个点以下的节点的不满意度。
Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会。当然,她会选择最方便的地点来举办这次集会。每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场。道路i连接农场A_i和B_i(1 <= A_i <=N; 1 <= B_i <= N),长度为L_i(1 <= L_i <= 1,000)。集会可以在N个农场中的任意一个举行。另外,每个牛棚中居住者C_i(0 <= C_i <= 1,000)只奶牛。在选择集会的地点的时候,Bessie希望最大化方便的程度(也就是最小化不方便程度)。比如选择第X个农场作为集会地点,它的不方便程度是其它牛棚中每只奶牛去参加集会所走的路程之和,(比如,农场i到达农场X的距离是20,那么总路程就是C_i*20)。帮助Bessie找出最方便的地点来举行大集会。考虑一个由五个农场组成的国家,分别由长度各异的道路连接起来。在所有农场中,3号和4号没有奶牛居住。
solution:
1、将树看成以1为根的一棵有根树。
2、用一个s
记录该节点以下的牛的个数。
3、用一个a
表示该节点为聚会地点时,奶牛们的不方便程度。
那么有:
s[ i ]=v[i]+s[ s(i) ];
a[ i ]+=a[ son(i) ]+s[son(i)]*w
a[ i ]+=(total - s[ i ])*w+(a[father(i) ]-a[ i ]-s[v]*w)
其中v[i] 表示该点的牛数目,total 表示总的牛数量,w 表示 father(i) 到i点的距离。
这样,进行两次DFS,第一次DFS则要得到s[]的值还有以这棵树来看时候的a[]值,
这个时候a[]值仅为a[ son(i) ] + s[ son(i) ]* w,
不算包括父亲在内的另一部分子树的不满意度,第二次DFS则要计算a[],
需要两次DFS的原因是,必须要用一个节点的不满意度已经求出,才能求出这个点以下的节点的不满意度。
#include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace std; const int M=100010; int n,cnt; bool vis[M]; long long s[M];//Sum long long a[M],res;//Unsatisfiable struct Node { int to; int w; Node(int a,int b) {to=a,w=b;} }; vector<Node> G[M]; void Dfs(int u) { vis[u]=true; for(int i=0;i<G[u].size();++i) { int v=G[u][i].to; int w=G[u][i].w; if(vis[v])continue; Dfs(v); s[u]+=s[v]; a[u]+=a[v]+s[v]*w; } } void Get(int u) { vis[u]=true; for(int i=0;i<G[u].size();++i) { int v=G[u][i].to; int w=G[u][i].w; if(vis[v])continue; a[v]+=(cnt-s[v])*w+(a[u]-a[v]-s[v]*w); res=min(res,a[v]); Get(v); } } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&s[i]); cnt+=s[i]; } for(int i=1;i<n;++i) { int a,b,c; scanf("%d %d %d",&a,&b,&c); G[a].push_back(Node(b,c)); G[b].push_back(Node(a,c)); } Dfs(1); res=a[1]; memset(vis,0,sizeof(vis)); Get(1); printf("%lld\n",res); return 0; }
相关文章推荐
- BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会( dp + dfs )
- BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会
- BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树
- BZOJ 1827: [Usaco2010 Mar]gather 奶牛大集会
- K短路 (A*算法) [Usaco2008 Mar]牛跑步&[Sdoi2010]魔法猪学院
- 【BZOJ1827】[Usaco2010 Mar]gather 奶牛大集会 树形DP
- 1827: [Usaco2010 Mar]gather 奶牛大集会 (树形DP)
- 嘴巴题4 「BZOJ1827」[Usaco2010 Mar] gather 奶牛大集会
- bzoj 1828: [Usaco2010 Mar]balloc 农场分配【贪心+线段树】
- 【BZOJ】1638: [Usaco2007 Mar]Cow Traffic 奶牛交通(dfs+dp)
- BZOJ 1782: [Usaco2010 Feb]slowdown 慢慢游( BIT + dfs )
- 【BZOJ 1827】 [Usaco2010 Mar]gather 奶牛大集会
- bzoj:1828: [Usaco2010 Mar]balloc 农场分配
- 1827: [Usaco2010 Mar]gather 奶牛大集会
- BZOJ1827 [Usaco2010 Mar]gather 奶牛大集会
- BZOJ1828: [Usaco2010 Mar]balloc 农场分配
- BZOJ 1782 [Usaco2010 Feb]slowdown 慢慢游 dfs序,树状数组
- bzoj1827[Usaco2010 Mar]gather 奶牛大集会 树上DP
- BZOJ 1828: [Usaco2010 Mar]balloc 农场分配 线段树 贪心
- bzoj 1827: [Usaco2010 Mar]gather 奶牛大集会