点分治

1.洛谷 点分治1

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=10000+299;
const int maxm=100+5;
const int maxk=10000000+29;
using namespace std;
int bo[maxk],fir[maxn],nxt[maxn*2],to[maxn*2],val[maxn*2],vis[maxn],root,ecnt;
int n,m,sum,dis[maxn],sz[maxn],qs[maxm],mx[maxn],ans[maxm],top[maxn],que[maxn];
void add(int u,int v,int w){
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
}
void dfs(int x,int fa){
    for(int i=1;i<=m;i++){
         if(qs[i]-dis[x]>=0&&bo[qs[i]-dis[x]]==top[x])  ans[i]=1;
        }
    for(int i=fir[x];i;i=nxt[i]){
        if(x==top[x]&&que[0]){
           for(int j=1;j<=que[0];j++)
            bo[dis[que[j]]]=x;
           que[0]=0;
        }
        int v=to[i];
        if(v==fa||vis[v]) continue;
        dis[v]=dis[x]+val[i];
        top[v]=top[x];
        que[++que[0]]=v;//避免同一子树中的误判,压入队列 
        dfs(v,x);
    }
}    
void get_root(int x,int fa){
    sz[x]=1; mx[x]=1;
    for(int i=fir[x];i;i=nxt[i]){
        int v=to[i];
        if(vis[v]||v==fa) continue;
        get_root(v,x);
        sz[x]+=sz[v];
        mx[x]=max(mx[x],sz[v]); 
    }
    mx[x]=max(mx[x],n-sz[x]);
    if(mx[x]<mx[root]) root=x;
}
void work(int x){
    dis[x]=0; 
    bo[0]=x;
    top[x]=x;
    vis[x]=1;
    dfs(x,0);
    for(int i=fir[x];i;i=nxt[i]){
        int v=to[i];
        if(vis[v]) continue;
        root=0;
        sum=sz[v];
        get_root(v,x);
        work(root);
    }
}
int main()
{
    scanf("%d%d",&n,&m); 
    sum=n; mx[0]=n+299;
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    for(int i=1;i<=m;i++)
    scanf("%d",&qs[i]);
    get_root(1,0);
    work(root);
    for(int i=1;i<=m;i++){
        if(ans[i]) printf("AYE\n");
        else printf("NAY\n");
    }
    return 0;
}
点分治 1

2.洛谷 聪聪可可

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=20000+299;
int ecnt,fir[maxn],nxt[maxn*2],to[maxn*2],val[maxn*2],vis[maxn],root,n; 
int ans,f[5],sz[maxn],mx[maxn],sum,dis[maxn];
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
void add(int u,int v,int w){
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w%3;
    nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w%3;
}
void dfs(int x,int fa){
    f[dis[x]]++;
    for(int i=fir[x];i;i=nxt[i]){
        int v=to[i];
        if(vis[v]||v==fa) continue;
        dis[v]=(dis[x]+val[i])%3;
        dfs(v,x);
    }
}
int cul(int x,int d){
    dis[x]=d; 
    f[0]=f[1]=f[2]=0; 
    dfs(x,0);
    return f[0]*f[0]+f[1]*f[2]*2;
}
void get_root(int x,int fa){
    sz[x]=1; mx[x]=0;
    for(int i=fir[x];i;i=nxt[i]){
        int v=to[i];
        if(v==fa||vis[v]) continue;
        get_root(v,x);
        sz[x]+=sz[v]; mx[x]=max(mx[x],sz[v]);
    }
    mx[x]=max(mx[x],sum-sz[x]);
    if(mx[x]<mx[root]) root=x;
}
void work(int x){
    ans+=cul(x,0); vis[x]=1;
    for(int i=fir[x];i;i=nxt[i]){
        int v=to[i];
        if(vis[v]) continue;
        ans-=cul(v,val[i]);
        sum=sz[v];
        root=0; get_root(v,x);
        work(root);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    mx[0]=n+1;
    sum=n;
    get_root(1,0);
    work(root);
    int t=gcd(n*n,ans);
    printf("%d/%d\n",ans/t,n*n/t);
    return 0;
}
聪聪可可

 

posted @ 2017-09-04 19:34  啊宸  阅读(119)  评论(0编辑  收藏  举报