HDU 5416 CRB and Tree(dfs+邻接表)——多校练习10
2015-08-21 11:12
453 查看
CRB and Tree
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)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.
Author
KUT(DPRK)
Source
2015 Multi-University Training Contest 10
/*********************************************************************/
题意:有一棵n个结点(结点记为0~n),n-1条加权边的树,定义f(u,v)为结点u与结点v之间所有边权值的异或值,即若u与v之间有e1,e2,e3,e4,e5这么五条边的话,f(u,v)=e1⊕e2⊕e3⊕e4⊕e5,现给你一个异或值s,问满足f(u,v)=s的无序对(u,v)有多少对。
放上出题人的解题报告:
首先,我们来证明一下f(u,v)=f(1,u)⊕f(1,v)
假设1到u之间有e6,e7,e8三条边,以及之前假设的u到v的五条边
f(u,v)=e1⊕e2⊕e3⊕e4⊕e5=e1⊕e2⊕e3⊕e4⊕e5⊕(e6⊕e6)⊕(e7⊕e7)⊕(e8⊕e8)=(e6⊕e7⊕e8)⊕(e1⊕e2⊕e3⊕e4⊕e5⊕e6⊕e7⊕e8)=f(1,u)⊕f(1,v)
所以我们只需dfs一遍,算出所有的f(1,u)值,存下每个异或值出现的次数
又因为若a⊕b=c,则a⊕c=b,所以由f(u,v)=f(1,u)⊕f(1,v)=s可得f(1,v)=f(1,u)⊕s
对于每次询问,我们只需加上对于每个结点u,f(1,u)⊕s值出现的次数即可
另外,s=0的情况比较特殊,需另外考虑,因为u==v的情况下,f(u,v)=f(u,u)=0
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 100005;
const int inf = 1000000000;
const int mod = 1000000007;
struct node
{
int to,next,w;
}e[2*N];
int h
,p,s
;
__int64 m[2*N];
void add_edge(int u,int v,int w)
{
e[p].to=v;
e[p].next=h[u];
e[p].w=w;
h[u]=p++;
}
void dfs(int u,int r)
{
int v;
for(int i=h[u];i+1;i=e[i].next)
{
v=e[i].to;
if(v==r)
continue;
s[v]=s[u]^e[i].w;
m[s[v]]++;
dfs(v,u);
}
}
int main()
{
int t,n,i,a,b,c,q,x,y;
__int64 ans,sum;
scanf("%d",&t);
while(t--)
{
p=0;
memset(h,-1,sizeof(h));
memset(m,0,sizeof(m));
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
}
s[1]=0;
dfs(1,-1);//dfs算出所有的f(1,u),并记录每个异或值出现的次数
scanf("%d",&q);
while(q--)
{
sum=ans=0;
scanf("%d",&x);
if(!x)//u==v的情况,即s=0
ans+=n;
for(i=2;i<=n;i++)
{
if(x==s[i])
ans++;
sum+=m[y=s[i]^x];
if(y==s[i])
sum--;
}
printf("%I64d\n",sum/2+ans);
}
}
return 0;
}菜鸟成长记
相关文章推荐
- ThinkPHP Nginx pathinfo rewrite 配置
- Spring-Data-Redis特性
- opencv图片格式转换
- HDU 5410 CRB and His Birthday (2015年多校比赛第10场)
- 机器学习--python之学会如何从文件逐行读取数据
- 如何printf64位整型!
- 代码实现UIPickerView
- (leetcode) Remove Duplicates from Sorted Array II
- hadoop随手笔记
- Java进阶01 String类
- Linq中的TakeWhile和SkipWhile的用法
- c# List<T>与ObservableCollection<T>
- Openstack kilo指南安装与实践(1)
- 测试Heartbeat
- Android中处理崩溃异常
- linux遍历目录C语言
- UVAlive 3662 Another Minimum Spanning Tree 莫队算法,曼哈顿最小生成树
- PostgreSQL学习手册-模式Schema(转)
- Quartz.net 的简单使用,创建定时任务
- 正则表达式1