码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5416 CRB and Tree dfs

时间:2015-08-20 20:56:12      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

链接

题解链接: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) ^ f(lca, root) == 0

所以 f(u,v) =( f(lca,u)^f(lca,root) ) ^ ( f(lca, v) ^ f(lca, root))

= f(root,u) ^ f(root, v)

然后用一个数组存下从根到任意一个点的路径异或值。

最后对每个询问,枚举以某个点为端点的路径个数即可。

因为这样算出来的path(u,v)是计算了2遍的,所以结果要/2

注意一下0的情况即可。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <vector>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <iomanip>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) pt(x / 10);
    putchar(x % 10 + '0');
}
using namespace std;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int N = 1e5 + 10;
typedef long long ll;
typedef pair<int, int> pii;
struct Edge {
    int from, to, dis, nex;
}edge[3 * N];
int head[N], edgenum;  //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根)  
void add(int u, int v, int w) {
    Edge E = { u,v,w,head[u] };
    edge[edgenum] = E;
    head[u] = edgenum++;
}
void init() { memset(head, -1, sizeof head); edgenum = 0; }

int n;
int mp[N*2];
void dfs(int u, int fa, int dep) {
    mp[dep]++;
    for (int i = head[u]; ~i; i = edge[i].nex) {
        int v = edge[i].to; if (v == fa)continue;
        dfs(v, u, dep ^ edge[i].dis);
    }    
}
ll ans;
int s;
void go(int u, int fa, int dep) {
//    mp[dep]--;
    ans += mp[s^dep];
    for (int i = head[u]; ~i; i = edge[i].nex) {
        int v = edge[i].to; if (v == fa)continue;
        go(v, u, dep ^ edge[i].dis);

    }
//    mp[dep]++;
}
int main() {
    int T; rd(T);
    while (T--) {
        init();
        rd(n);
        for (int i = 1, u, v, d; i < n; i++) {
            rd(u); rd(v); rd(d);
            add(u, v, d);
            add(v, u, d);
        }
        memset(mp, 0, sizeof mp);
        dfs(1, 1, 0);
        int Q; rd(Q);
        while (Q--) {
            rd(s);
            ans = 0;
            go(1, 1, 0);
            if (s == 0)ans += n;
            ans >>= 1;
            pt(ans); puts("");
        }
    }
    return 0;
}/*
1
2
1 2 0
10
0

 */


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5416 CRB and Tree dfs

标签:

原文地址:http://blog.csdn.net/qq574857122/article/details/47813351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!