• P2634 [国家集训队]聪聪可可


    P2634 [国家集训队]聪聪可可

    点分治,很模板的做法,不说什么了吧。
    就是calc的方法再多说一句。
    ans加的应该是图1红线的情况,但是会出现图2的多余情况,要减掉

    #include<bits/stdc++.h>
    using namespace std;
    const int N=20005;
    struct edge {
    	int nxt,to,val;
    } e[N<<1];
    int head[N],num_edge;
    void add(int from,int to,int val) {
    	++num_edge;
    	e[num_edge].nxt=head[from];
    	e[num_edge].to=to;
    	e[num_edge].val=val;
    	head[from]=num_edge;
    }
    int n,siz[N],rt,mn,d[N],sum;
    bool used[N];
    void getrt(int u,int fa) {
    	int mx=0;siz[u]=1;
    	for(int i=head[u]; i; i=e[i].nxt) {
    		int v=e[i].to;
    		if(used[v]||v==fa)continue;
    		getrt(v,u);
    		siz[u]+=siz[v];
    		mx=max(mx,siz[v]);
    	}
    	mx=max(mx,sum-siz[u]);
    	if(mx<mn)mn=mx,rt=u;
    }
    int a[3],ans;
    void getdis(int u,int fa) {
    	d[u]%=3;++a[d[u]];
    	for(int i=head[u]; i; i=e[i].nxt) {
    		int v=e[i].to;
    		if(v==fa||used[v])continue;
    		d[v]=d[u]+e[i].val;
    		getdis(v,u);
    	}
    
    }
    int calc(int u,int dd) {
    	a[1]=a[2]=a[0]=0;
    	d[u]=dd%3;
    	getdis(u,0);
    	return a[0]*a[0]+a[1]*a[2]+a[2]*a[1];
    }
    void solve(int u) {
    	ans+=calc(u,0);
    	used[u]=true;
    	for(int i=head[u]; i; i=e[i].nxt) {
    		int v=e[i].to;
    		if(used[v])continue;
    		ans-=calc(v,e[i].val);
    		mn=n;
    		sum=siz[v];
    		getrt(v,u);
    		solve(rt);
    	}
    }
    int main() {
    	scanf("%d",&n);
    	for(int i=1,x,y,w; i<n; ++i) {
    		scanf("%d%d%d",&x,&y,&w);w%=3;
    		add(x,y,w);add(y,x,w);
    	}
    	sum=n;mn=n;getrt(1,0);
    	solve(rt);
    	int t=__gcd(ans,n*n);
    	printf("%d/%d\n",ans/t,n*n/t);
    	return 0;
    }
    
  • 相关阅读:
    Java统计程序运行时间(转)
    有符号定点数的表示方法
    移位运算符
    索引
    self与super的区别(转)
    Java经典题型(未完成)
    ObjectiveC 的 self 和 super 详解
    边界计算与不对称边界
    各种排序总结
    运算符的优先级
  • 原文地址:https://www.cnblogs.com/zzctommy/p/12321173.html
Copyright © 2020-2023  润新知