蓝桥刷题--N皇后和最近公共祖先

1.N皇后

#include<iostream>
using namespace std;

const int N = 12;
int vis[N][N], n, ans;

void dfs(int dep)
{
    // 在这个搜索中dep表示行,i表示列
    // 1 搜索出口
    if(dep == n + 1)
    {
        ans++;
        return;
    }
    // 2 继续搜索
    for(int i = 1; i <= n; ++i)
    {
        // 2.1 排除非法情况
        if(vis[dep][i])
            continue;
        // 2.2 改变状态
        for(int _i = 1; _i <= n; ++_i)
            vis[_i][i]++;
        for(int _i = dep, _j = i; _i >= 1 && _j >= 1; --_i, --_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i <= n && _j >= 1; ++_i, --_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i >= 1 && _j <= n; --_i, ++_j)
            vis[_i][_j]++;
        for(int _i = dep, _j = i; _i <= n && _j <= n; ++_i, ++_j)
            vis[_i][_j]++;
        // 2.3 下一层
        dfs(dep + 1);
        // 2.4 还原现场
        for(int _i = 1; _i <= n; ++_i)
            vis[_i][i]--;
        for(int _i = dep, _j = i; _i >= 1 && _j >= 1; --_i, --_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i <= n &&  _j >= 1; ++_i, --_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i >= 1 && _j <= n; --_i, ++_j)
            vis[_i][_j]--;
        for(int _i = dep, _j = i; _i <= n && _j <= n; ++_i, ++_j)
            vis[_i][_j]--;
    }
}

int main()
{
    cin >> n;
    dfs(1);
    cout << ans << "\n";
    return 0;
}

2.最近公共祖先LCA查询

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
int n;
vector<int> arr[N]; // 定义一个向量数组 

int dep[N], fa[N][24];

void dfs(int u, int father) // 预处理 
{
	dep[u] = dep[father] + 1;
	fa[u][0] = father;
	for(int i = 1;i <= 20; ++ i)
	{
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
	}
	
	for(const auto &x : arr[u])
		if(x != father) // 只能往下探索 
			dfs(x, u);
}

int lca(int a, int b) // 求 a , b 的最近公共祖先 
{
	if(dep[a] < dep[b])swap(a, b);
	// 先跳到同一层
	for(int i = 20;i >= 0; -- i)
	{
		if(dep[fa[a][i]] >= dep[b])
			a = fa[a][i];
		// 如果 b 是 a 祖先,返回 b 
		if(a == b)return a;
	} 
	 
	// 再跳到lac的下一层
	for(int i = 20;i >= 0; -- i)
	{
		if(fa[a][i] != fa[b][i])
		{
			a = fa[a][i];
			b = fa[b][i];
		}	
	} 
	return fa[a][0];
}

int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for(int i = 1;i < n; ++ i)
	{
		int u, v; cin >> u >> v;
		arr[u].push_back(v);
		arr[v].push_back(u);
	}
	
	dfs(1, 0);
	
	int q; cin >> q; // q 次查询 
	while(q -- )
	{
		int a, b; cin >> a >> b;
		cout << lca(a, b) << '\n';
	}
}

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值