bzoj 2435 //2435:[NOI2011]道路修建 //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=2435
更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录
洛谷3.09s / 68.38MB / 714B C++
//2435:[NOI2011]道路修建
//在线测评地址https://www.luogu.org/problem/P2052
//缺的图详见https://wenku.baidu.com/view/270a90f04693daef5ef73da6.html内容是0<=ci<=10^6
//该题有几个问题,1是统计每个点左侧,右侧的国家数,这个算法复杂度就比较惊人。
//2是求最小花费。
//此文https://www.cnblogs.com/cold-cold/p/10029766.html思路写得不错,摘抄如下:
/*
每个边的实际花费费用为道路的权乘以道路两端的国家个数之差的绝对值,那么如果我们预处理每个点的子树的大小siz
通过树的遍历来遍历每一条边,因为是从我们求siz时使用的根出发,那么对于u->v的一条边,v的那一头的国家数量就是size[v],而u的那一头的国家数量就是n-size[v]
我们将两个数相减取绝对值abs(n-2*size[v]),再乘以边权,就是每个边的实际花费费用
注意:不开long long 似乎要WA
*/
//此文https://www.luogu.org/problemnew/solution/P2052 作者: AThousandMoon 更新时间: 2018-12-14 13:24 代码写得很不错。
//0<=ci<=10^6,n=1000000,long long是省不了了。
//样例通过,提交AC.2019-10-23
#include
#include
#define maxn 1000100
#define LL long long
int n,head[maxn],cnt=0,size[maxn];
LL ans=0;
struct node{
int to,next,w;
}e[maxn*2];//无向图
void add_edge(int u,int v,int w){
cnt++,e[cnt].to=v,e[cnt].w=w,e[cnt].next=head[u],head[u]=cnt;
}
LL myabs(LL a){//绝对值
if(a<0)a=-a;
return a;
}
void dfs(int x,int fa){
int b,v,w;
size[x]=1;
for(b=head[x];b;b=e[b].next){
v=e[b].to,w=e[b].w;
if(v!=fa){
dfs(v,x);
ans+=(LL)myabs(n-2*size[v])*w;
size[x]+=size[v];
}
}
}
int main(){
int i,u,v,w;
memset(head,0,sizeof(head));
scanf("%d",&n);
for(i=1;i
add_edge(u,v,w),add_edge(v,u,w);
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}
86496 kb | 7056 ms | C++/Edit | 1018 B |
//在bzoj提交代码,出现问题Runtime_Error 99568 kb 7336 ms C++/Edit 955 B 2019-10-27 10:07
//找了份https://www.bbsmax.com/A/GBJrOYG50e/ 代码,进行对比研究。
//修改,提交,以下代码能在bzoj里AC.2019-10-27 11:41
//几处修改如下
/*
int myabs(int a){//LL myabs(LL a){//绝对值
size[x]+=size[v];//与下行交换位置后,能在bzoj AC.2019-10-27 11:27
ans+=(LL)myabs(n-2*size[v])*w;
*/
#include
#include
#define LL long long
#define maxn 1000100
struct node{
int to,next,w;
}e[maxn*2];//无向图
int n,head[maxn],cnt=0,size[maxn];
LL ans=0;
void add_edge(int u,int v,int w){
cnt++,e[cnt].to=v,e[cnt].w=w,e[cnt].next=head[u],head[u]=cnt;
}
int myabs(int a){//LL myabs(LL a){//绝对值
if(a<0)a=-a;
return a;
}
void dfs(int x,int fa){
int b,v,w;
size[x]=1;
for(b=head[x];b;b=e[b].next){
v=e[b].to,w=e[b].w;
if(v!=fa){
dfs(v,x);
size[x]+=size[v];//与下行交换位置后,能在bzoj AC.2019-10-27 11:27
ans+=(LL)myabs(n-2*size[v])*w;
}
}
}
int main(){
int i,u,v,w;
scanf("%d",&n);
memset(head,0,sizeof(head));
for(i=1;i
add_edge(u,v,w),add_edge(v,u,w);
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}