• bzoj2152: 聪聪可可


    题目链接

    bzoj2152: 聪聪可可

    题解

    其实本来想找点分的题做,然后就用dp水了
    当然,也有好好用点分水一遍的QWQ
    dp,维护子树中点到子树跟的距离,%3分类的个数,转移很好写吧 :上,
    点分:维护当前树中点到根的距离分类,统计答案好些吧,因为会在当前树的某棵子树下出现非最短路径,容斥一下就好了,下
    当然,dp复杂度是更优的
    dp

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
        int x = 0,f = 1;
        char c = getchar(); 
        while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar(); } 
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f; 
    } 
    const int maxn = 40007; 
     
    struct node { 
        int v,w,next; 
    }edge[maxn << 1]; 
    int head[maxn],num = 0; 
    inline void add_edge(int u,int v,int w) { 
        edge[++ num].v = v;edge[num].w = w;edge[num].next = head[u]; head[u] = num; 
    } 
    int n; 
    int dp[maxn][3]; 
    int ans = 0; 
    void dfs(int x,int fa) { 
        dp[x][0] = 1; 
        for(int i = head[x];i ;i = edge[i].next) { 
            int v = edge[i].v; 
            if(v == fa) continue; 
            dfs(v,x); 
            for(int j = 0;j < 3;++ j) { 
                int tmp = (j + edge[i].w) % 3; 
                ans += dp[v][j] * dp[x][(3 - tmp) % 3] * 2; 
            } 
            //printf("%d
    ",ans); 
            for(int j = 0;j < 3;++ j) 
                dp[x][(j + edge[i].w) % 3] += dp[v][j]; 
        }   
    } 
    int gcd(int x,int y) { 
        if(!y) return x;else return gcd(y,x % y); 
    } 
    int main() { 
        n = read(); 
        for(int u,v,w,i = 1;i < n;++ i)  {
            u = read(),v = read(),w = read(); 
            add_edge(u,v,w),add_edge(v,u,w);    
        } 
        dfs(1,0);   
        ans += n; 
        int g = gcd(ans,n * n); 
        printf("%d/%d
    ",ans / g,n * n/g);  
        return 0; 
    }  
    
    
    

    点分

    #include<cstdio> 
    #include<algorithm> 
    inline int read() { 
        int x = 0,f = 1;
        char c = getchar(); 
        while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar(); } 
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f; 
    } 
    const int maxn = 40007; 
    struct node { 
        int v,w,next; 
    } edge[maxn << 1]; 
    int head[maxn],num = 0,ans = 0; 
    bool vis[maxn]; 
    inline void add_edge(int u,int v,int w) { 
         edge[++ num].v = v;edge[num].w = w;edge[num].next = head[u]; head[u] = num; 
    } 
     
    int n,son[maxn],dis[maxn],cnt[maxn],f[maxn],root,tot; 
    void get_root(int x,int fa) {
        son[x] = 1;f[x] = 0; 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
            if(v == fa || vis[v]) continue; 
            get_root(v,x); 
                son[x] += son[v];f[x] = std::max(f[x],son[v]);  
        } 
        f[x] = std::max(f[x],tot - son[x]); 
        if(f[x] < f[root]) root = x;     
    } 
    void get_dis(int x,int fa) { 
        cnt[dis[x]] ++;
        for(int i = head[x];i;i = edge[i].next) {
            int v = edge[i].v; 
                if(vis[v] || v == fa) continue ;
            dis[v] = (dis[x] + edge[i].w) % 3;      
            get_dis(v,x); 
        } 
    } 
    int calc(int x,int Dis) { 
        dis[x] = Dis;cnt[0] = cnt[1] = cnt[2] = 0; 
        get_dis(x,0); 
        return cnt[1] * cnt[2] * 2 + cnt[0] * cnt[0]; 
    } 
    void sol(int x) { 
        ans += calc(x,0),vis[x] = 1; 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
                if(vis[v]) continue; 
            ans -= calc(v,edge[i].w); 
            root = 0;tot = son[v]; 
            get_root(v,0);sol(root); 
        } 
    } 
    int gcd(int x,int y) { 
        return !y ? x : gcd(y,x % y); 
    } 
    int main() { 
        n  = read(); 
        for(int u,v,w,i = 1;i < n;++ i) { 
            u = read(),v = read(),w = read() % 3; 
            add_edge(u,v,w),add_edge(v,u,w); 
        } 
        tot = n;f[0] = n + 1; 
        get_root(1,0); 
        sol(root); 
        int g = gcd(ans,n * n); 
        printf("%d/%d
    ",ans / g,n * n / g); 
        return 0; 
    }   
    
  • 相关阅读:
    Java中的4种代码块
    Java enum(枚举)的用法详解(转)
    Java 可变参数列表
    SQL Server 查询处理中的各个阶段(SQL执行顺序)
    SQL Server 数据查询 整理
    MYSQL常用命令
    SQL的主键和外键约束(转)
    Servlet工作原理(转)
    servlet、genericservlet、httpservlet之间的区别(转)
    关于MyEcplise中常见的问题和解决方案
  • 原文地址:https://www.cnblogs.com/sssy/p/9230853.html
Copyright © 2020-2023  润新知