概述
Problem 1 :奶牛大集会
(gather.pas/c/cpp)
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号没有奶牛居住。
1 3 4 5
@--1--@--3--@--3--@[2]
[1] |
2
|
@[1]
2
Bessie可以在五个农场中的任意一个举办集会,下面就是在每个位置举办集会的不方便值的统计表。
集会地点 ----- 不方便程度 ------
B1 B2 B3 B4 B5 Total
1 0 3 0 0 14 17
2 3 0 0 0 16 19
3 1 2 0 0 12 15
4 4 5 0 0 6 15
5 7 8 0 0 0 15
如果Bessie在农场1举办集会,那么每个农场各自的不方便值分别是
农场 1 0 -- 到达不需要时间!
农场 2 3 -- 总的距离是 2+1=3 x 1 奶牛 = 3
农场 3 0 -- 没奶牛!
农场 4 0 -- 没奶牛!
农场 5 14 -- 总的距离是 3+3+1=7 x 2 奶牛 = 14
因此,总的不方便值是17。
最小的不方便值是15,当在3号,4号或者5号农场举办集会的时候。
题目名称: gather
输入格式
* 第一行:一个整数N
* 第二到N+1行:第i+1行有一个整数C_i
* 第N+2行到2*N行,第i+N+1行为3个整数:A_i,B_i和L_i。
样例输入(gather.in):
5
1
1
0
0
2
1 3 1
2 3 2
3 4 3
4 5 3
输出格式:
* 第一行:一个值,表示最小的不方便值。
样例输出(gather.out):
15
30%的数据n<=20
50%的数据n<=5000
80%的数据n<=50000
100%的数据n<=100000
这是题解上说的(没怎么看懂。。。) |
这道题n2的算法比较显然,先对每个点做一次bfs,求出任意两点间距离,然后枚举集会地点,直接计算即可。 期望得分:50分(实际没有这么多。。=_=!!) 考虑这样一个问题,如果我将集会地点从u移动到u的子节点v会发生什么情况呢?设u到v的距离为L,对于v这棵子树上的任意一个节点,到集会地点的距离都减少了L,对于非v子树上的任意节点,到集会地点的距离都增加了L。 我们对每课子树都维护一个sum表示这棵子树的所有节点总共上居住的牛的头数那么从u移动到v总代价的变化量(增加量)为 L*(sumroot-2*sumv) 这样,只需要两遍dfs就可以算出每个节点上举行集会的代价 usaco的Linux评测系统下能过所有的数据,复杂度为O(n) 我本人提供的标程在这个基础上还加了一个优化,即每次只移动到增量为负的那个叶节点,复杂度还是O(n) |
我本人是借鉴了另外一个题解才出来的http://www.cnblogs.com/xiao_wu/archive/2010/06/01/1749416.html
下面是我的代码,有一个点有点小问题。。。。
C++ Code
/*
http://blog.csdn.net/jiangzh7
C++ Code
*/
#include<cstdio>
#include<string>
#include<list>
#include<iostream>
using namespace std;
#define MAXN 100010
#define oo 999999999
typedef long long LL;
typedef struct{int pos,z;}tnode;
list<tnode> first[MAXN];
list<tnode> dis[MAXN];
int n,c[MAXN];
LL total,sum[MAXN],ans[MAXN];
bool h[MAXN];
void dfs(LL x)//求出以x为根的数的总奶牛头数
{
h[x]=true;
list<tnode> pnode=first[x];
tnode p;
while(!pnode.empty())
{
p=pnode.front();
LL y=p.pos,z=p.z;
if(!h[y])
{
dfs(y);
sum[x]+=sum[y];
ans[x]+=ans[y]+sum[y]*z;
}
pnode.pop_front();
}
sum[x]+=c[x];
}
void dfs2(LL x)
{
h[x]=true;
list<tnode> pnode=first[x];
tnode p;
while(!pnode.empty())
{
tnode p=pnode.front();
LL y=p.pos,z=p.z;
if(!h[y])
{
ans[y]+=(total-sum[y])*z+(ans[x]-ans[y]-sum[y]*z);
dfs2(y);
}
pnode.pop_front();
}
}
int main()
{
freopen("gather.in","r",stdin);
freopen("gather.out","w",stdout);
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
{ scanf("%d",&c[i]);total+=c[i]; }
int x,y,z;
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
tnode p;
p.pos=y;p.z=z;
first[x].push_front(p);
p.pos=x;p.z=z;
first[y].push_front(p);
}
dfs(1);
memset(h,0,sizeof(h));
dfs2(1);
LL min=ans[1];
for(i=1;i<n;i++)
min<?=ans[i];
cout<<min;
return 0;
}
大家要是能看出来是哪错了的话,请联系我,可以站内联系,也可以jiangzh7@yeah.net或者QQ:905865858
最后
以上就是踏实大叔为你收集整理的【带权中位数】奶牛大集会的全部内容,希望文章能够帮你解决【带权中位数】奶牛大集会所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复