zoukankan      html  css  js  c++  java
  • JZOJ 1967.【2011集训队出题】聪聪可可

    题目

    【2011集训队出题】聪聪可可

    思路

    看看做做 阴阳 这道题
    极力推荐
    自从做了这道题后,这些题就变成秒切的题了

    很容易想到求节点到分治中心的距离,然后 (mod 3)
    那么在求根节点一棵子树的答案时直接加上 (dis[(3-x) mod 3]) 的个数
    用个桶 (buc) 来记录,若当前节点的 (dis mod 3) 后结果为 (0),说明它到跟也为合法路径,此时 (res) 要额外 (+1)
    统计完一个子树的贡献后再将子树的信息加入桶中
    统计完所有子树,重新选根前再 (dfs) 一遍清除 (buc)

    (Code)

    #include<cstdio>
    #include<iostream>
    using namespace std;
    
    const int N = 2e4 + 5;
    int n , h[N] , tot , size , siz[N] , son[N] , dis[N] , use[N] , ans , rt , buc[5];
    
    struct edge{
    	int to , nxt , w;
    }e[N * 2];
    
    inline void add(int x , int y , int z)
    {
    	e[++tot].to = y;
    	e[tot].w = z;
    	e[tot].nxt = h[x];
    	h[x] = tot;
    }
    
    inline void getrt(int x , int fa)
    {
    	son[x] = 0 , siz[x] = 1;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa || use[v]) continue;
    		getrt(v , x);
    		siz[x] += siz[v];
    		son[x] = max(son[x] , siz[v]);
    	}
    	son[x] = max(son[x] , size - siz[x]);
    	rt = son[x] < son[rt] ? x : rt;
    }
    
    inline void getdis(int x , int fa)
    {
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa || use[v]) continue;
    		dis[v] = (dis[x] + e[i].w) % 3;
    		getdis(v , x);
    	}
    }
    
    inline int dfs(int x , int fa)
    {
    	int res = 0;
    	res += buc[(3 - dis[x]) % 3] + (dis[x] == 0 ? 1 : 0);
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa || use[v]) continue;
    		res += dfs(v , x);
    	}
    	return res;
    }
    
    inline void fill(int x , int fa)
    {
    	buc[dis[x]]++;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa || use[v]) continue;
    		fill(v , x);
    	}
    }
    
    inline void clear(int x , int fa)
    {
    	buc[dis[x]]--;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (v == fa || use[v]) continue;
    		clear(v , x);
    	}
    	dis[x] = 0;
    }
    
    inline int calc(int x)
    {
    	dis[x] = 0;
    	getdis(x , 0);
    	int res = 0;
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (use[v]) continue;
    		res += dfs(v , x) , fill(v , x);
    	}
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (use[v]) continue;
    		clear(v , x);
    	}
    	return res;
    }
    
    inline void divide(int x)
    {
    	use[x] = 1 , ans += calc(x);
    	for(register int i = h[x]; i; i = e[i].nxt)
    	{
    		int v = e[i].to;
    		if (use[v]) continue;
    		size = siz[v] , rt = 0;
    		getrt(v , x) , divide(rt);
    	}
    }
    
    inline int gcd(int a , int b){return b == 0 ? a : gcd(b , a % b);}
    
    int main()
    {
    	scanf("%d" , &n);
    	int u , v , w;
    	for(register int i = 1; i < n; i++) 
    	{
    		scanf("%d%d%d" , &u , &v , &w);
    		add(u , v , w) , add(v , u , w);
    	}
    	son[0] = 2e9 , size = n , rt = 0;
    	getrt(1 , 0) , divide(rt);
    	ans = ans * 2 + n;
    	int tmp = n * n , d = gcd(ans , tmp);
    	printf("%d/%d" , ans / d , tmp / d);
    }
    
  • 相关阅读:
    用电脑Python控制Arduino
    Arduino-LiquidCrystal_I2C 液晶库
    Arduino通讯串口
    nginx statistics in multi-workers
    Nginx RTMP 模块 nginx-rtmp-module 指令详解
    windows下搭建nginx-rtmp服务器
    超实用压力测试工具-ab工具
    (总结)Nginx配置文件nginx.conf中文详解
    NGINX conf 配置文件中的变量大全 可用变量列表及说明
    「自己开发直播」实现nginx-rtmp-module多频道输入输出与权限控制
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13411854.html
Copyright © 2011-2022 走看看