zoukankan      html  css  js  c++  java
  • bzoj 2152: 聪聪可可

    点分治时维护出t[0],t[1],t[2],分别表示路径长度%3之后的数量。

    答案就是t[0]^2+2*t[1]*t[2]

    (能不能依次处理子树呢?????感觉这个题可以。。。。)

     1 #include<bits/stdc++.h>
     2 #define N 100005
     3 #define M 10000005
     4 #define LL long long
     5 #define inf 0x3f3f3f3f
     6 using namespace std;
     7 inline int ra()
     8 {
     9     int x=0,f=1; char ch=getchar();
    10     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    11     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    12     return x*f;
    13 }
    14 int n,K,cnt,sum,ans,root;
    15 int head[20005],deep[20005],d[20005],f[20005],size[20005],t[5];
    16 bool vis[20005];
    17 struct data{int to,next,v;}e[40005];
    18 void insert(int x, int y, int v){e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].v=v; head[x]=cnt;}
    19 void getroot(int x, int fa)
    20 {
    21     size[x]=1; f[x]=0;
    22     for (int i=head[x];i;i=e[i].next)
    23     {
    24         if (e[i].to==fa || vis[e[i].to]) continue;
    25         getroot(e[i].to,x);
    26         size[x]+=size[e[i].to];
    27         f[x]=max(f[x],size[e[i].to]);
    28     }
    29     f[x]=max(f[x],sum-size[x]);
    30     if (f[x]<f[root]) root=x;
    31 }
    32 void getdeep(int x, int fa)
    33 {
    34     t[d[x]]++;
    35     for (int i=head[x];i;i=e[i].next)
    36     {
    37         if (vis[e[i].to] || e[i].to==fa) continue;
    38         d[e[i].to]=(d[x]+e[i].v)%3;
    39         getdeep(e[i].to,x);
    40     }
    41 }
    42 int cal(int x, int tot)
    43 {
    44     d[x]=tot; 
    45     memset(t,0,sizeof(t));
    46     getdeep(x,0);
    47     return t[0]*t[0]+t[1]*t[2]*2;
    48 }
    49 void solve(int x)
    50 {
    51     ans+=cal(x,0); vis[x]=1;
    52     for (int i=head[x];i;i=e[i].next)
    53     {
    54         if (vis[e[i].to]) continue;
    55         ans-=cal(e[i].to,e[i].v);
    56         sum=size[e[i].to]; root=0;
    57         getroot(e[i].to,0);
    58         solve(root);
    59     }
    60 }
    61 int main()
    62 {
    63     n=ra();
    64     for (int i=1; i<n; i++)
    65     {
    66         int x=ra(),y=ra(),v=ra()%3;
    67         insert(x,y,v); insert(y,x,v); 
    68     }
    69     sum=n; f[0]=inf;
    70     getroot(1,0); 
    71     solve(root);
    72     int t=__gcd(ans,n*n);
    73     printf("%d/%d
    ",ans/t,n*n/t);
    74     return 0;
    75 }
  • 相关阅读:
    VC++ 之 文件操作
    Delphi7 API(5) 消息篇:WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE
    VC++ 之 输入/输出类库(二)
    VB 访问控制面板
    Delphi7 API(4) 消息_重绘
    Lisp简明教程
    一次快速排序错误引发的思考(2)
    一次快速排序错误引发的思考(1)
    Common Lisp编译程序的小技巧
    暴风影音5免去广告的小技巧
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6419236.html
Copyright © 2011-2022 走看看