zoukankan      html  css  js  c++  java
  • HDU 5416 CRB and Tree

    题目大意:
    T, T组测试数据
    给你一个n有n个点,下标是从 1 开始的。这个是一棵树,然后下面是n-1条边,
    每条边的信息是 s,e,w 代表 s-e的权值是w
    然后是一个Q代表Q次询问。
    每次询问是一个数字a,  代表 所有路径想异或后的值是 a的路径有多少条。
    (注:  自己到自己的异或值是0,若a是0要考虑自己到自己)
     
    题目分析:
    从根节点开始进行一遍DFS求出所有点到 跟节点的异或值。也就得出来了根节点到达其他任何一个点的异或值。
    比如 a 是跟节点到A的异或值, b是根节点到B的异或值
    那么A->B的路径上的异或值就是  a^b.然后把所有的异或值桶排一下。
    注意一点 a^b 的值是可能大于10W的,最大是260000多
     
     
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define INF 0x3fffffff
    typedef long long LL;
    const LL  maxn = 300005;
    const LL  mod  = 1e9+7;
    
    bool vis[maxn];
    int k, Head[maxn], n, Max = 0;
    LL num[maxn];
    struct node
    {
        int e, next, w;
    }Edge[maxn*2];
    
    void AddEdge(int s,int e,int w)
    {
        Edge[k].w = w;
        Edge[k].e = e;
        Edge[k].next = Head[s];
        Head[s] = k;
        k ++;
    }
    
    void DFS(int root,int a)
    {
        vis[root] = true;
        num[a] ++;
        for(int i=Head[root]; i!=-1; i=Edge[i].next)
        {
            int e = Edge[i].e;
            if(vis[e] == true)
                continue;
            DFS(e, a^Edge[i].w);
        }
    }
    
    int main()
    {
    
        int Q, T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            k = 0;
            memset(Head, -1, sizeof(Head));
            memset(vis, false, sizeof(vis));
            memset(num, 0, sizeof(num));
            for(int i=0; i<n-1; i++)
            {
                int s, e, w;
                scanf("%d %d %d",&s, &e, &w);
                AddEdge(s, e, w);
                AddEdge(e, s, w);
            }
            DFS(1, 0);
    
            scanf("%d", &Q);
            while( Q --)
            {
                int a;
                LL ans = 0;
                scanf("%d", &a);
                if(a == 0)
                    ans += n;
                for(int i=0; i<=270000; i++)
                {
                    if(a == 0)
                        ans += num[i]*(num[i]-1)/2;
                    else if(i < (a^i) && num[i] && num[a^i])
                        ans += num[i]*num[a^i];
                }
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    [JSOI2016]最佳团体
    CF125E MST Company
    CF482C Game with Strings
    CF379F New Year Tree
    CF1051F The Shortest Statement
    小a和uim之大逃离
    新魔法药水
    翻硬币
    [CQOI2017]小Q的棋盘
    UVA11729突击战
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4746918.html
Copyright © 2011-2022 走看看