zoukankan      html  css  js  c++  java
  • 「FJ2014集训 采药人的路径」

    题目

    考虑一下把(0)看成(-1),那么就是找到一条边权和为(0)的路径,且这条路径可以被分成两段,边权和都是(0)

    没有第二个限制就是点分裸题了

    其实有了第二个限制还是点分裸题

    考虑那个断点肯定会存在于当前分治重心的某一边,或者直接在分治重心上,我们在求每个点到分治重心的距离的时候判断一下上面能否有一个点成为断点就好了

    具体做法就是开个桶,判断每个点的祖先是否有一个和它的分治重心的距离相等

    之后就把点分成了两类,一类是到分治重心的路径上存在断点,一类是不存在的,显然不存在的只能和存在的拼成路径,同时还要满足距离和加起来为(0)就好了

    于是开两个桶分别维护一下就好了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define LL long long
    #define re register
    #define maxn 100005
    inline int read() {
        char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    struct E{int v,nxt,w;}e[maxn<<1];
    int n,m,num,now,rt,S;LL ans;
    int head[maxn],sum[maxn],mx[maxn],vis[maxn],pre[maxn];
    int f[maxn<<1],tax[maxn<<1][2],top[2],st[maxn<<1][2];
    inline void add(int x,int y,int z) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;}
    void getroot(int x,int fa) {
        sum[x]=1,mx[x]=0;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]||e[i].v==fa) continue;
            getroot(e[i].v,x);sum[x]+=sum[e[i].v];
            mx[x]=max(mx[x],sum[e[i].v]);
        }
        mx[x]=max(mx[x],S-sum[x]);
        if(mx[x]<now) rt=x,now=mx[x];
    }
    void getdis(int x,int fa,int o) {
        pre[x]=pre[fa]+o;
        if(f[pre[x]+n]) {
            st[++top[1]][1]=x;
            if(f[pre[x]+n]>1&&pre[x]==0) ans++;
        }
            else st[++top[0]][0]=x;
        f[pre[x]+n]++;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]||e[i].v==fa) continue;
            getdis(e[i].v,x,e[i].w);
        }
        f[pre[x]+n]--;
    }
    void clear(int x,int fa) {
        tax[n+pre[x]][0]=tax[n+pre[x]][1]=0;pre[x]=0;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]||e[i].v==fa) continue;
            clear(e[i].v,x);
        }
    }
    void dfs(int x) {
        vis[x]=1;f[0+n]=1;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]) continue;
            top[0]=top[1]=0;getdis(e[i].v,x,e[i].w);
            for(re int j=1;j<=top[0];j++) 
                ans+=tax[n-pre[st[j][0]]][1];
            for(re int j=1;j<=top[1];j++) 
                ans+=tax[n-pre[st[j][1]]][1]+tax[n-pre[st[j][1]]][0];
            for(re int j=1;j<=top[0];j++) tax[n+pre[st[j][0]]][0]++;
            for(re int j=1;j<=top[1];j++) tax[n+pre[st[j][1]]][1]++;
        }f[0+n]=0;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]) continue;
            clear(e[i].v,x);
        }
        for(re int i=head[x];i;i=e[i].nxt) {
            if(vis[e[i].v]) continue;
            S=sum[e[i].v],now=n,getroot(e[i].v,0),dfs(rt);
        }
    }
    int main() {
        n=read();
        for(re int x,y,z,i=1;i<n;i++) {
            x=read(),y=read(),z=read();
            if(!z) z=-1;add(x,y,z),add(y,x,z);
        }
        now=n,S=n,getroot(1,0);dfs(rt);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    php4的一个创建xml的类
    ecshop在模板里调用广告位的代码
    文件导出dbf功能实现
    [转] 处事22计、心态24条、伤心50句、礼仪73、学会长大20!
    在线客服 qq,msn,skype, outlook 链接
    解决动网论坛Bug缺少对象: 'Application(...).documentElement.selectSingleNode(...)'
    创建一个SharePoint 样式(Creating a SharePoint Theme)
    Sharepoint Portal Services 2003开发环境
    [译]Hour 7 Teach.Yourself.WPF.in.24.Hours
    远程桌面连接无法最大化的解决办法
  • 原文地址:https://www.cnblogs.com/asuldb/p/10470848.html
Copyright © 2011-2022 走看看