zoukankan      html  css  js  c++  java
  • BZOJ2152 聪明可可 点分治

    题意传送门

    思路:基本的点分治思路,num数组记录从u点开始路径长度分别为1或者2或者3的路径长度(取模3意义下),然后做一个简单的容斥就好了。

      为了避免计数的麻烦,<u,u>这样的点单独计算,也就是最后的答案加上n就可以了。

      bzoj不支持c14,我的代码是在洛谷交的。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dep(i,b,a) for(int i=b;i>=a;--i)
    #define clr(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    #define pii pair<int,int >
    using namespace std;
    typedef long long ll;
    ll rd()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int maxn=20010;
    const int inf=0x3f3f3f3f;
    int T,n,m;
    struct edge{
        int to,w;
    };
    vector<edge >ve[maxn];
    ll ans=0;
    int rt,mx,dis[maxn];
    ll num[3];
    int siz[maxn],size;
    bool vis[maxn];
    int u,v,w;
    void getrt(int u,int p){
        siz[u]=1;
        int tmp=0;
        for(auto &st:ve[u]){
            int v=st.to;
            if(vis[v]||v==p)continue;
            getrt(v,u);
            siz[u]+=siz[v];
            tmp=max(tmp,siz[v]);
        }
        tmp=max(size-siz[u],tmp);
        if(tmp<mx){
            mx=tmp;
            rt=u;
        }
    }
    void getdis(int u,int p){
        dis[u]%=3;
        num[dis[u]]++;
        for(auto &st:ve[u]){
            int v=st.to,w=st.w;
            if(v==p||vis[v])continue;
            dis[v]=(dis[u]+w)%3;
            getdis(v,u);
        }
    }
    ll cal(int u,int val){
        dis[u]=val;
        clr(num,0);
        getdis(u,0);
        ll sum=2*num[1]*num[2]+2*(num[0]-1)+(num[0]-1)*(num[0]-1-1);
        return sum;
    }
    void dfs(int u){
        vis[u]=1;
        ans+=cal(u,0);
        for(auto &st:ve[u]){
            int v=st.to,w=st.w;
            if(vis[v])continue;
            ans-=cal(v,w);
            size=siz[v];
            mx=inf;
            getrt(v,0);
            dfs(rt);
        }
    }
    int main(){
        cin>>n;
        rep(i,1,n-1){
            u=rd(),v=rd(),w=rd();
            w=w%3;
            ve[u].pb({v,w});
            ve[v].pb({u,w});
        }
        size=n;
        mx=inf;
        getrt(1,0);
        dfs(1);
        ans+=n;
        ll an2=1ll*n*n;
        ll gc=__gcd(an2,ans);
        printf("%lld/%lld
    ",ans/gc,an2/gc);
    }
  • 相关阅读:
    ALV实时刷新功能的实现
    sap中批量导入Excel表格中的数据
    从se11新建的表维护中,给维护的数据做限制处理,例如,只允许输入vp开头的数据
    abap之ranges使用
    Abap中LOOP循环时使用AT FIRST. 传数过程中出现一串 ******** ------解决办法
    Django项目-创建第一个页面
    Python3创建django项目
    Python3安装Pyyaml
    Appium命令行环境搭建及参数使用
    c# ABP 中开启新的事务
  • 原文地址:https://www.cnblogs.com/mountaink/p/11407542.html
Copyright © 2011-2022 走看看