Two way search summary

Posted by jpt62089 on Thu, 03 Feb 2022 02:13:09 +0100

Bidirectional search

1, Bidirectional search

When the start state and end state are given, the efficiency will be very low and the search tree will be very large if you use ordinary search to search from the start to the bottom;

Therefore, you can use two-way search and search from the starting point and the end point to the middle at the same time. When you search to the same state, add the values searched from the starting point and the end point to get the search of the final value;

Generally, when the "initial state" and "final state" are given, two-way search can be considered;

2, Bidirectional DFS

first D F S DFS In DFS, first search the first half of the space and store all the reachable values;

the second D F S DFS In DFS, search the second half of the space, and then query whether it has appeared in the first half of the space;

3, Bidirectional BFS

two-way B F S BFS BFS maintains two pairs of columns, q 1 q1 q1 , q 2 q2 q2 , q 1 q1 q1 maintains the status of searching from the starting point, q 2 q2 q2 maintains the status of searching from the end point. If a status is found to be deleted at the same time when expanding the status q 1 q1 q1 and q 2 q2 q2 is extended to, and the answer is found at this time;

Put the start status into q1;
Put the end status into q2;
Mark start status as 1;
Mark the end status as 2;
while (q1 Not empty && q2 Not empty) {
    if (q1 size > q2 size) {
        Fetch queue q2 Team leader element;
    } else {
        Fetch queue q1 Team leader element;
    }
    Loop traversal takes out the extensible state of the element {
        if (from q1 take out) {
    		Mark as 1, put in q1 queue;
    	} else {
			Mark as 2, put in q2 queue;
        }
        if (The status is marked as 1 and 2 at the same time) {
            Find the answer and the search ends;
        }
    }
}

You can also use only one pair of columns, that is, open another variable in the queue to mark where to start the search;

4, Examples

Navigation system

subject

Little Q came to a random country. The country consists of n cities and M two-way roads. Because this country advocates randomness, m edges are generated by randomly selecting two ends. Curious little Q wants to make k random trips here, and the starting and ending points of each trip are also randomly selected. Before each departure, he will use the navigation system to calculate the minimum number of roads to pass between two points. Please write a program to help Xiao Q calculate the shortest circuit between two points

input

The first line contains three positive integers n, m, K (2 < = n < = 100000,1 < = m < = 300000,1 < = k < = 10000), representing the number of points, edges and queries respectively.

Next m lines, each with two positive integers U_ i,v_ I (1 < = u_i, v_i < = n), indicating a two-way road. The input data guarantees that there will be no double edges and self rings.

Next k lines, two positive integers u per line_ i,v_ I (1 < = u_i, v_i < = n), indicating an inquiry.

The input data is guaranteed to be generated randomly, and all except the examples meet the requirements of n = 100000 and M = 300000.

There are three groups of data in this question.

output

Output k lines, an integer for each line, that is, the minimum number of sides. If there is no solution, output - 1.

thinking

This question gives a starting point and an ending point, so consider two-way search. When expanding the state, expand the points connected by each point;

Use the adjacency table to record the graph. When asking, use and look up the set to judge whether the two points are connected;

code

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAXN 300005
using namespace std;
int n, m, k, father[MAXN];
bool flag1[MAXN], flag2[MAXN];
vector < int > g[MAXN];
struct node {
	int x, z, f;
};
void firstset(int n) {
	for (int i = 1; i <= n; i++) {
		father[i] = i;
	}
	return;
}
int findset(int x) {
	if (x == father[x]) return x;
	return father[x] = findset(father[x]);
}
void push(int x, int y) {
	father[findset(x)] = findset(y);
	return;
}
int bfs(int s, int e) {
	queue < node > q;
	memset(flag1, false, sizeof(flag1));
	memset(flag2, false, sizeof(flag2));
	flag1[s] = true, flag2[e] = true;
	q.push( node ( { s, 0, 1 } ) );
	q.push( node ( { e, 0, 2 } ) );
	while (!q.empty()) {
		node t = q.front();
		q.pop();
		for (int i = 0; i < g[t.x].size(); i++) {
			if (t.f == 1) {
				flag1[g[t.x][i]] = true;
				q.push( node ( { g[t.x][i], t.z + 1, 1 } ) );
			} else {
				flag2[g[t.x][i]] = true;
				q.push( node ( { g[t.x][i], t.z + 1, 2 } ) );
			}
			if (flag1[g[t.x][i]] == true && flag2[g[t.x][i]] == true) {
				int ans = t.z + 1;
				if (t.f == 2) {
					while (!q.empty()) {
						node z = q.front();
						if (z.x == g[t.x][i] && z.f == 1) {
							ans += z.z;
							break;
						}
						q.pop();
					}
				} else {
					while (!q.empty()) {
						node z = q.front();
						if (z.x == g[t.x][i] && z.f == 2) {
							ans += z.z;
							break;
						}
						q.pop();
					}
				}
				return ans;
			}
		}
	}
}
int main() {
	scanf("%d %d %d", &n, &m, &k);
	firstset(n);
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		g[x].push_back(y);
		g[y].push_back(x);
		push(x, y);
	}
	for (int i = 1; i <= n; i++) {
		sort(g[i].begin(), g[i].end());
	}
	for (int i = 1; i <= k; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		if (x == y) printf("0\n");
		else if (findset(x) != findset(y)) printf("-1\n");
		else printf("%d\n", bfs(x, y));
	}
	return 0;
} 

Topics: Algorithm