• Luogu P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat… 题解


    闲扯

    我做这道题的时候究极脑瘫。。

    第一次提交忘开 (long long) ,只有 (50) 分;

    第二次提交输出忘开 (long long) ,只有 (70) 分。。。

    无语至极。。

    题面

    题面

    Solution

    要找出一个点,使得 (sumlimits_{j!=rt} dis_jcdot c_j) 最小。

    考虑换根。

    先求出以 (1) 号点为根节点时的答案,同时记录子树里面的奶牛数。对于每一条边,它的贡献为 (valcdot size_{to})

    然后 (DFS) 换根。考虑将根节点转至 (u) 时,只有 (rt) 连向 (u) 的边会改变答案。具体的:

    1. 对于以 (u) 为根结点的子树所包含的奶牛,他们要走的路程减少了 (val) ,对于答案的贡献要减去 (size_ucdot val)
    2. 对于其他的奶牛,他们要走的路程增加了 (val) ,对于答案的贡献要加上 ((size_1-size_u)cdot val) 。(因为 (size_1) 表示奶牛的总数)

    然后最后的答案为 (minlimits_{i=1}^n ans_i)

    Code

    #include<bits/stdc++.h>
    #define del(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mid ((l+r)>>1)
    #define lowbit(x) (x&(-x))
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>il read(T &x){
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    template<class T>il print(T x){
    	if(x/10) print(x/10);
    	putchar(x%10+'0');
    }
    ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
    it qpow(int x,int m,int mod){
    	int res=1,bas=x%mod;
    	while(m){
    		if(m&1) res=(res*bas)%mod;
    		bas=(bas*bas)%mod,m>>=1;
    	}
    	return res%mod;
    }
    const int MAXN = 1e5+5;
    int n,c[MAXN],u,v,d,head[MAXN],num_edge,size[MAXN];
    ll ans,now;
    struct Edge{
    	int next,to,dis;
    	Edge(){}
    	Edge(int next,int to,int dis):next(next),to(to),dis(dis){}
    }edge[MAXN<<1];
    il add_edge(int u,int v,int dis){
    	edge[++num_edge]=Edge(head[u],v,dis),head[u]=num_edge;
    	edge[++num_edge]=Edge(head[v],u,dis),head[v]=num_edge;
    }
    il DFS(int u,int fa){
    	size[u]=c[u];
    	for(ri i=head[u];i;i=edge[i].next){
    		if(edge[i].to==fa) continue;
    		DFS(edge[i].to,u),size[u]+=size[edge[i].to];
    		ans+=1ll*size[edge[i].to]*edge[i].dis;
    	}
    }
    il DFS1(int u,int fa,ll res){
    	ans=min(ans,res);
    	for(ri i=head[u];i;i=edge[i].next){
    		if(edge[i].to==fa) continue;
    		DFS1(edge[i].to,u,res-1ll*edge[i].dis*size[edge[i].to]+1ll*edge[i].dis*(size[1]-size[edge[i].to]));
    	}
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n);
    	for(ri i=1;i<=n;++i) read(c[i]);
    	for(ri i=1;i<n;++i) read(u),read(v),read(d),add_edge(u,v,d);
    	DFS(1,0),now=ans;
    	for(ri i=head[1];i;i=edge[i].next) DFS1(edge[i].to,1,now-1ll*edge[i].dis*size[edge[i].to]+1ll*edge[i].dis*(size[1]-size[edge[i].to]));
    	printf("%lld",ans);
    	return 0;
    }
    

    总结

    做题一定要算好数据范围,确定好是使用 (int) 还是用 (long long) ,不然炸了就不好了。

  • 相关阅读:
    DIV编辑器中当keydowm时获得内部其他元素的位置
    javascript 比较运算符分析
    JS编码注意事项,不断更新中
    ahjesus 获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome
    keycode对应主要键的关系
    关于jquery的remove方法
    根据EntityFramework写的重写sql语句的类
    查询sql表的详细信息
    让div span等元素能响应键盘事件
    你会用英语吵架吗?(学会99句,走遍全世界)
  • 原文地址:https://www.cnblogs.com/TheShadow/p/11390947.html
Copyright © 2020-2023  润新知