zoukankan      html  css  js  c++  java
  • 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞

    3697: 采药人的路径

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 681  Solved: 246
    [Submit][Status][Discuss]

    Description

    采药人的药田是一个树状结构,每条路径上都种植着同种药材。
    采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
    采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。

    Input

    第1行包含一个整数N。
    接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。

    Output

    输出符合采药人要求的路径数目。

    Sample Input

    7
    1 2 0
    3 1 1
    2 4 0
    5 2 0
    6 3 1
    5 7 1

    Sample Output

    1

    HINT

    对于100%的数据,N ≤ 100,000。

    Source

    3127: [Usaco2013 Open]Yin and Yang

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 116  Solved: 82
    [Submit][Status][Discuss]

    Description

    Farns (1 <= N <= 100,000) which are connected by N-1 edges such that he can reach any barn from any other. Farmer John wants to choose a path which starts and ends at two different barns, such that he does not traverse any edge twice. He worries that his path might be a little long, so he also wants to choose another "rest stop" barn located on this path (which is distinct from the start or the end). Along each edge is a herd of cows, either of the Charcolais (white hair) or the Angus (black hair) variety. Being the wise man that he is, Farmer John wants to balance the forces of yin and yang that weigh upon his walk. To do so, he wishes to choose a path such that he will pass by an equal number of Charcolais herds and Angus herds-- oth on the way from the start to his rest stop, and on theway from the rest stop to the end. Farmer John is curious how many different paths he can choose that  are "balanced" as described above. Two paths are different only if they consist of different setsof edges; a path should be counted only once even if there are multiple valid "rest stop" locationsalong the path that make it balanced. Please help determine the number of paths Farmer John can cho

    Input

    * Line 1: The integer N.
    * Lines 2..N: Three integers a_i, b_i and t_i, representing the two barns that edge i connects. t_i 
    is 0 if the herd along that edge is Charcolais, and 1 if the herd is Angus.

    Output

    Line 1: One integer, representing the number of possible paths Farmer John can choose from.

    Sample Input

    7
    1 2 0
    3 1 1
    2 4 0
    5 2 0
    6 3 1
    5 7 1
    INPUT DETAILS:
    There are 7 barns and 6 edges. The edges from 1 to 2, 2 to 4 and 2 to 5 have Charcolais herds along
    them.

    Sample Output

    1
    OUTPUT DETAILS:
    No path of length 2 can have a suitable rest stop on it, so we can only consider paths of length 4.
    The only path that has a suitable rest stop is 3-1-2-5-7, with a rest stop at 2.

    HINT

    Source

    Gold

    Solution

    这道题有点厉害

    首先肯定想到点分治,问题在于如何统计答案

    首先对于阴阳边,我们可以赋权值+1/-1,这样路径阴阳数目就比较直观了

    定义$f[i][0/1]$表示当前子树中路径和为$i$的路径个数,0/1表示路径上是否存在前缀为$i$的点

    定义$g[i][0/1]$表示之前前子树中路径和为$i$的路径个数,0/1同理

    那么对答案的贡献就是$g[0][0]*f[0][0]+sum (g[-i][0]]*f[i][1]+g[-i][1]*f[i][0]+g[-i][1]*f[i][1])$

    要注意考虑下标为负的情况...全部+N即可

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int 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; 
    }
    #define MAXN 100010
    #define LL long long
    int N;
    struct EdgeNode{int next,to,val;}edge[MAXN<<1];
    int head[MAXN],cnt=1;
    void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
    void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
    int size[MAXN],maxx[MAXN],root,Sz; bool visit[MAXN];
    void DFSRoot(int now,int last)
    {
        size[now]=1; maxx[now]=0;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last && !visit[edge[i].to])
                {
                    DFSRoot(edge[i].to,now);
                    size[now]+=size[edge[i].to];
                    maxx[now]=max(maxx[now],size[edge[i].to]);
                }
        maxx[now]=max(maxx[now],Sz-size[now]);
        if (maxx[now]<maxx[root]) root=now;
    }
    int deep[MAXN],maxd,md,mark[MAXN<<1],D[MAXN<<1];
    LL f[MAXN<<1][2],g[MAXN<<1][2],ans;
    void DFS(int now,int last)
    {
        maxd=max(maxd,deep[now]);
        if (mark[D[now]]) f[D[now]][1]++; else f[D[now]][0]++;
        mark[D[now]]++;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last && !visit[edge[i].to])
                {
                    deep[edge[i].to]=deep[now]+1;
                    D[edge[i].to]=D[now]+edge[i].val;
                    DFS(edge[i].to,now);
                }
        mark[D[now]]--;
    }
    void Get(int x,int val)
    {
        D[x]=N+val; deep[x]=1;
        maxd=1; DFS(x,0); md=max(maxd,md);
        ans+=(g[N][0]-1)*f[N][0];
        for (int i=-maxd; i<=maxd; i++)
            ans+=g[N-i][1]*f[N+i][1]+g[N-i][0]*f[N+i][1]+g[N-i][1]*f[N+i][0];
        for (int i=N-maxd; i<=N+maxd; i++)
            g[i][0]+=f[i][0],g[i][1]+=f[i][1],f[i][0]=f[i][1]=0;
    }
    void Divide(int x)
    {
        visit[x]=1;
        g[N][0]=1; md=0;
        for (int i=head[x]; i; i=edge[i].next)
            if (!visit[edge[i].to]) Get(edge[i].to,edge[i].val);
        for (int i=-md; i<=md; i++) g[N+i][0]=g[N+i][1]=0;
        for (int i=head[x]; i; i=edge[i].next)
            if (!visit[edge[i].to])
                {
                    Sz=size[edge[i].to]; root=0;
                    DFSRoot(edge[i].to,x);
                    Divide(root);
                }
    }
    int main()
    {
        N=read();
        for (int x,y,z,i=1; i<=N-1; i++)
            x=read(),y=read(),z=read(),InsertEdge(x,y,z? z:-1);
        Sz=maxx[root=0]=N;
        DFSRoot(1,0);
        Divide(root);
        printf("%lld
    ",ans);
        return 0;
    } 
  • 相关阅读:
    深入浅出HTTP请求(转自http://www.cnblogs.com/yin-jingyu/archive/2011/08/01/2123548.html)
    IOS定位
    webView(简单的浏览器)
    Get&Post登录
    IOS多媒体
    IOS VFL屏幕自适应
    IOS中在自定义控件(非视图控制器)的视图跳转中 代理方法与代码块的比较
    单例设计的定义
    动画
    多线程
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5791431.html
Copyright © 2011-2022 走看看