让我们异或吧 - 洛谷
这题首先给了我们一个树;
所以,我们需要知道如何存储一棵树;
我们知道树是一种特殊的图,图的存储一共有两种方法:
(1) 邻接矩阵 (2) 邻接表
邻接矩阵:
就是一个二维数组 , f[ i ][ j ]表示 i -> j 有边,如果边赋权值的话,就是f[ i][ j ] 的值;这个办法空间复杂度比较高,而且不是很实用(我们不用这个);
邻接表:
这个其实就是我们给每个结点开一个链表,进行存储,我们不考虑存储的顺序(其实就是单链表)我们用代码来进行简要的说明;
// h[N]:n个结点,我们给每个结点开一个单链表(这里用数组模拟);
// e[M]:存储结点;
// ne[M]:当前结点的下一个结点;
// w[M]:当前结点指向下一个结点的边的值;
// idx:结点的索引;
int h[N],e[M],ne[M],w[M],idx;
// 给 a -> b 加一条边 ,值为 v;
void add(int a,int b,int v)
{
e[idx] = b;
w[idx] = v;
ne[idx] = h[a];
h[a] = idx++;
}
头插法:(我们存的是索引 idx)
明白了图的存储之后,我们就可以看题了;对了,对于有向图和无向图,我们都可以看成有向图(无向图看成双向的有向图);
这个题就是让我们在这颗树上维护两个结点的异或值;
事实上,我们维护的两个结点的异或值:
d[u] ^ d[temp] ^ d[temp] ^ d[v] = d[u] ^ d[v];
因此我们要维护一个d[N] 数组,用来存储我们结点的异或值,实际上是 1 到其他结点的异或值,也可以理解为我们将 1 作为转折点。我们路径上dfs一遍后,直接查询就可了;
#include
#include
#include
#include
#include
#define x first
#define y second
#define _for(i,s,t) for(int i = (s);i <=t ; i++)
#define FAST ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair PII;
const int N = 100010,M = N * 2;
int h[N],e[M],ne[M],w[M],idx;
bool st[N];
int n,m,d[N];
void add(int a,int b,int v)
{
e[idx] = b;
w[idx] = v;
ne[idx] = h[a];
h[a] = idx++;
}
bool dfs(int id,int val)
{
d[id] = val;
st[id] = true;
for(int i = h[id]; i != -1 ; i = ne[i])
{
int j = e[i];
if(!st[j]) dfs(j,val ^ w[i]);
}
}
int main()
{
scanf("%d",&n);
memset(h,-1,sizeof h);
_for(i,1,n - 1)
{
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
add(a,b,w);
add(b,a,w);
}
scanf("%d",&m);
dfs(1,0);
while(m --)
{
int a,b;
memset(st,0,sizeof st);
scanf("%d%d",&a,&b);
cout<< (d[a] ^ d[b])<
[NOI2011] 道路修建 - 洛谷
这个题也是给了我们一个图,我们根据题目抽象出的模型就是:
搜索每一个点,计算以该点为分界点两边城市的差值乘以该条路径上的权值即可;
#include
#include
#include
#include
#include
#define x first
#define y second
#define _for(i,s,t) for(int i = (s);i <=t ; i++)
#define FAST ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair PII;
const int N = 1000010;
int n;
int h[N],e[N << 1],ne[N << 1],w[N << 1],size[N],idx;
LL res;
bool st[N];
inline void add(int a,int b,int v)
{
e[idx] = b;
w[idx] = v;
ne[idx] = h[a];
h[a] = idx++;
}
inline void dfs(int u)
{
st[u] = true;
size[u] = 1;
for(int i = h[u]; i != -1 ; i = ne[i])
{
int j = e[i] , v = w[i];
if(!st[j])
{
dfs(j);
res += 1LL * abs(n - 2 * size[j]) * v;
size[u] += size[j];
}
}
}
int main()
{
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i =1 ;i < n ;i++)
{
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
add(a,b,v);
add(b,a,v);
}
dfs(1);
printf("%lld",res);
return 0;
}