HDU 5416——CRB and Tree——————【DFS搜树】

CRB and Tree

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 967    Accepted Submission(s): 308

Problem Description

CRB has a tree, whose vertices are labeled by 1, 2, …, N. They are connected by N – 1 edges. Each edge has a weight.
For any two vertices u and v(possibly equal), f(u,v) is xor(exclusive-or) sum of weights of all edges on the path from u to v.
CRB’s task is for given s, to calculate the number of unordered pairs (u,v) such that f(u,v) = s. Can you help him?

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer N denoting the number of vertices.
Each of the next N - 1 lines contains three space separated integers a, b and c denoting an edge between a and b, whose weight is c.
The next line contains an integer Q denoting the number of queries.
Each of the next Q lines contains a single integer s.
1 ≤ T ≤ 25
1 ≤ N ≤ 105
1 ≤ Q ≤ 10
1 ≤ a, b ≤ N
0 ≤ c, s ≤ 105
It is guaranteed that given edges form a tree.

Output

For each query, output one line containing the answer.

Sample Input

1

3

1 2 1

2 3 2

3

2

3

4

Sample Output

1

1

0

Hint

For the first query, (2, 3) is the only pair that f(u, v) = 2.
For the second query, (1, 3) is the only one.
For the third query, there are no pair (u, v) such that f(u, v) = 4.

题目大意:给你一棵n个顶点n-1条边的树,每条边有一个权重,定义f(u,v)为结点u到结点v的边权异或值的和,让你求在该树上有多少f(u,v)=s的无序对。

解题思路:由于异或的性质。a^a=0。f(u,v)=f(1,u)^f(1,v)。f(u,v)=s  =>  f(1,u)^f(1,v)=s  =>   f(1,v)=f(1,u)^s。那么我们可以枚举u,然后得出f(1,v)为 f(1,u)^s的有多少个。对于s为0的情况,我们发现对于f(1,u)^0的结果还是f(1,u)我们在计算的时候会加一次f(1,u)本身的情况。那么我们最后只需要加上n就可以满足f(u,v)=f(u,u)的情况了。

如样例:

555

3

1 2 1

1 3 1

1

0

如果不加上n且没除以2之前的结果会是5。如果加上n那么结果就是8。最后除以2以后就是4。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+200;
int n,tot;
struct Edge{
    int to,w,next;
    Edge(){}
    Edge(int too,int ww,int nextt){
        to=too;w=ww;next=nextt;
    }
}edges[maxn*3];
typedef long long INT;
int head[maxn*2],val[maxn*2];
int times[maxn*2];
void init(){
    tot=0;
    memset(head,-1,sizeof(head));
    memset(times,0,sizeof(times));
    memset(val,0,sizeof(val));
}
void addedge(int fro , int to,int wei){
    edges[tot]=Edge(to,wei,head[fro]);
    head[fro]=tot++;
    edges[tot]=Edge(fro,wei,head[to]);
    head[to]=tot++;
}
void dfs(int u,int fa){
    times[val[u]]++;
    for(int i=head[u];i!=-1;i=edges[i].next){
        Edge &e=edges[i];
        if(e.to==fa)
            continue;
        val[e.to]=val[u]^e.w;
        dfs(e.to,u);
    }
    return ;
}
int main(){
    //  freopen("1011.in","r",stdin);
   // freopen("why.txt","w",stdout);
    int t , m, a,b,c ,s;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
        }
        dfs(1,-1);
        scanf("%d",&m);
        while(m--){
            INT ans=0;
            scanf("%d",&s);
            for(int i=1;i<=n;++i){
                if(times[val[i]^s]){
                    ans+=times[val[i]^s];
                }
            }
            if(s==0)
                ans+=n;
            printf("%lld\n",ans/2);
        }
    }
    return 0;
}

  

时间: 2024-10-19 20:46:33

HDU 5416——CRB and Tree——————【DFS搜树】的相关文章

HDU 5416 CRB and Tree dfs

链接 题解链接:http://www.cygmasot.com/index.php/2015/08/20/hdu_5416/ 题意: 给定n个点的树 下面n-1行给出边和边权 下面q个询问 每个询问一个数字s 询问有多少条路径使得路径的边权异或结果 == s 结果%(1e9+7) 询问不超过10组. 思路: 设路径{u,v}的边权异或结果为 f(u,v) 设lca 为u v的最近公共祖先 首先得到一个结论,f(u,v) =f(lca, u) ^ f(lca, v) 因为f(lca, root)

Hdu 5416 CRB and Tree (bfs)

题目链接: Hdu 5416 CRB and Tree 题目描述: 给一棵树有n个节点,树上的每条边都有一个权值.f(u,v)代表从u到v路径上所有边权的异或值,问满足f(u,v)==m的(u, v)有多少中情况(u, v有可能相同)? 解题思路: 由于xor的特殊性质.x^x=0,对于求f(u, v) == f(u, 1) ^ f(1, u). 又因为x^y == z可以推出x^z == y,对于f(u, 1) ^ f(1, v) == m可以转化为m ^ f(1, v) == f(u, 1)

hdu 5416 CRB and Tree(dfs+前缀和)

题意: 在一棵树上有n个点,n-1条边,每条边都有一个权值. 令f(u,v)等于u到v这条路径上的前缀和. 现在给你Q次询问(Q<=10) 询问f(u,v)=s的路径有多少条. 解析: 由于Q比较小可以直接利用O(n)复杂度的算法来做. 先用sum[u]保存下,从根节点到u的异或和是多少. 用一个hash map来保存,sum[u]出现了多少次. 每次就查询hash map中s ^ sum[u]出现了多少次. 查询的总和除以2就是最终结果. 注意: 如果s=0时,f(u,u)也满足条件,所以还要

HDU 5416 CRB and Tree (技巧)

题意:给一棵n个节点的树(无向边),有q个询问,每个询问有一个值s,问有多少点对(u,v)的xor和为s? 注意:(u,v)和(v,u)只算一次.而且u=v也是合法的. 思路:任意点对之间的路径肯定经过LCA的,但是如果如果知道某个点t到根的路径xor和为e,那么就能够得知 x^e=s中的x应该是多少,那就算有多少点到根的xor和为x即可.e是表示t到根的,所以而x也是其他点到根的路径xor和,两个点他们的LCA到根这段会被算2次,那么xor就为0了. (1)DFS算出每个点到根的路径xor和,

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的异或

hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~

题目: 链接:点击打开链接 题意: 输入n个点,要求选m个点满足连接m个点的m-1条边权值和sum与点的权值和ans使得sum/ans最小,并输出所选的m个点,如果有多种情况就选第一个点最小的,如果第一个点也相同就选第二个点最小的........ 思路: 求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~ 数据量小,暴力枚举~~~~~dfs暴力枚举C(M,N)种情况. 枚举出这M个点之后,Sum(point weight)固定,进行prim或者K

hdu 5412 CRB and Queries(线段树套笛卡尔树 - 动态区间第k大)

题目链接:hdu 5412 CRB and Queries 首先对所有出现过的值排序,建立线段树,每个线段树的节点是一棵笛卡尔树,笛卡尔树记录区间下标值. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; #define lson(x) (x<<1) #define rson(x) ((x<<

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

[poj3321]Apple Tree(dfs序+树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26762   Accepted: 7947 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been