16哈理工新生赛 J Another Tree (树上BFS)

    xiaoxiao2021-12-15  47

    题目链接:点击打开链接

    Another Tree Time Limit: 1000 MSMemory Limit: 32768 K Total Submit: 42(16 users)Total Accepted: 15(14 users)Rating: Special Judge: No Description

    给出一棵有N个节点(2 <= N <= 500000)N-1条边的树,每条边拥有一个长度L(1 <= L <= 500000)

    定义:

    (1)  path(u, v) = 顶点uv之间的最短路。

    (2)  xor-distance(u, v) = epath(u,v)length(e),⊕代表异或操作。

    请计算出有多少对点的xor-distance的值等于K0 <= K <= 500000)。(v != u 并且 pair(u,v) = pair(v,u))。

    Input

    第一行是一个整数T,表示有T组测试数据。

    接下来T组测试数据,每组测试数据开始为两个正整数NK,接下来N-1行每行包含三个整数u,v,L(0 <= u,v <= N-1),代表树中存在一条顶点为uv,边长为L的边。

    Output

    每组一行,输出点对的个数。

    Sample Input

    2

    4 1

    0 1 1

    1 2 3

    2 3 2

    3 0

    0 1 7

    0 2 7

    Sample Output

    2

    1

    Source2016级新生程序设计全国邀请赛

    题解:就是给你n个数字,问有多少对数字异或后等于k,在树上BFS去找到这些数字,然后统计找到的数字数字和K值出现的次数,将他们加到答案中, 最后除以2就是对数了。

    AC代码:

    #include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<map> using namespace std; #define N 500005 struct Node { int to,w; Node(int _to,int _w):to(_to),w(_w){} }; /* struct Node { int to,w; Node(int to,int w) { this->to = to; this->w = w; } }; */ vector<Node> v[N]; queue<int> q; map<int,long long> K_num; int vis[N],dis[N]; void bfs(int s) { while(!q.empty()) q.pop(); q.push(s); vis[s] = 1; dis[s] = 0; while(!q.empty()) { int now = q.front(); //printf("%d\n",now); q.pop(); K_num[dis[now]]++; //printf("tot[%d]=%d\n",dis[now],tot[dis[now]]); int len = v[now].size(); //当前节点now的大小 for(int i = 0; i < len; i++) { int next = v[now][i].to; int next_w = v[now][i].w; //printf("next=%d next_w=%d\n",next,next_w); if(vis[next]==0) { vis[next] = 1; dis[next] = dis[now]^next_w; //printf("dis[%d]=%d\n",next,dis[next]); q.push(next); } } } } int main() { int t,n,k,x,y,w; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); for(int i = 0; i < n; i++) v[i].clear(); for(int i = 1; i < n; i++) { scanf("%d%d%d",&x,&y,&w); v[x].push_back(Node(y,w)); v[y].push_back(Node(x,w)); } K_num.clear(); memset(vis,0,sizeof(vis)); // puts("**************"); bfs(0); //puts("**************"); long long ans = 0; for(int i = 0; i < n; i++) { //printf("dis[%d]=%d\n",i,dis[i]); if(k==0) ans += K_num[ k^dis[i] ]/2; else ans += K_num[ k^dis[i] ]; } ans = ans/2; printf("%lld\n",ans); } return 0; } /* 2 4 1 0 1 1 1 2 3 2 3 2 3 0 0 1 7 0 2 7 */ /* 2 1 */

    转载请注明原文地址: https://ju.6miu.com/read-1000216.html

    最新回复(0)