深度优先搜索(DFS) --- 提高篇

让我们异或吧 - 洛谷

这题首先给了我们一个树;

所以,我们需要知道如何存储一棵树;

我们知道树是一种特殊的图,图的存储一共有两种方法:

(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)

深度优先搜索(DFS) --- 提高篇_第1张图片

明白了图的存储之后,我们就可以看题了;对了,对于有向图和无向图,我们都可以看成有向图(无向图看成双向的有向图);

这个题就是让我们在这颗树上维护两个结点的异或值;

深度优先搜索(DFS) --- 提高篇_第2张图片

 事实上,我们维护的两个结点的异或值:

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;
} 

你可能感兴趣的:(图论,算法,dfs,深度优先遍历)