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


    基础点分治。

    点分治的模板基础上改一下即可。

    询问树上长度模数是3的路径

    //询问有多少路径的长度加起来是3的倍数
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    int n;
    vector<pair<int,int> > g[maxn];
    int vis[maxn],rt,sz[maxn],Tsz,wt[maxn],arr[maxn],cnt;
    long long ans;
    void getRoot (int u,int pre) {
    	sz[u]=1;
    	wt[u]=0;
    	for (pair<int,int> it:g[u]) {
    		int v=it.first;
    		if (!vis[v]&&v!=pre) {
    			getRoot(v,u);
    			sz[u]+=sz[v];
    			wt[u]=max(wt[u],sz[v]);
    		}
    	}
    	wt[u]=max(wt[u],Tsz-sz[u]);
    	if (wt[rt]>wt[u]) rt=u;
    }
    void dfs1 (int u,int dep,int pre) {
    	arr[++cnt]=dep;
    	for (pair<int,int> it:g[u]) {
    		int v=it.first;
    		if (v!=pre&&!vis[v]) dfs1(v,dep+it.second,u);
    	}
    }
    int cc[4];
    long long calc (int u,int dep) {
    	cnt=0;
    	dfs1(u,dep,0);
    	memset(cc,0,sizeof(cc));
    	for (int i=1;i<=cnt;i++) cc[arr[i]%3]++;
    	long long ans=1ll*cc[0]*cc[0]+1ll*cc[1]*cc[2]+1ll*cc[1]*cc[2];
    	return ans;
    }
    void dfs (int u) {
    	ans+=calc(u,0);
    	vis[u]=1;
    	for (pair<int,int> it:g[u]) {
    		int v=it.first;
    		if (!vis[v]) {
    			ans-=calc(v,it.second);//容斥减掉非法路径 
    			rt=0;
    			Tsz=sz[v];
    			getRoot(v,0);
    			dfs(rt);
    		} 
    	}
    }
    int main () {
    	scanf("%d",&n);
    	for (int i=1;i<n;i++) {
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		g[u].push_back(make_pair(v,w));
    		g[v].push_back(make_pair(u,w)); 
    	}
    	wt[rt=0]=1e9;
    	Tsz=n;
    	getRoot(1,0);
    	dfs(rt);
    	long long fm=1ll*n*n;
    	long long gg=__gcd(ans,fm);
    	ans/=gg;
    	fm/=gg;
    	printf("%lld/%lld",ans,fm);
    }
  • 相关阅读:
    字符串加密和解密的常类
    vs2013中使用nuget下载cefsharp winform包
    序列积第m小元素 二分答案优化
    贪心 park
    struct结构体 重载运算符
    最小生成树kruskal 知识点讲解+模板
    c++快读与快输模板
    MZOJ #82 总统竞选
    MZOJ #83 位运算
    MZOJ #81 最小得分和
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15034557.html
Copyright © 2020-2023  润新知