【蓝桥杯】dfs专题


DFS专题

题库:在线题库_在线做题_智能评测_蓝桥云课题库 - 蓝桥云课 (lanqiao.cn)

1.小朋友崇拜圈(拓扑排序 + dfs图的遍历)

题意:找最大的圈(环),输出结果。

思路:一个环中每一个点的入度至少为1,那么入度为0的点不可能构成环,因此拓扑排序将入度为1的点去掉,然后dfs遍历得到每一个环的大小,去最值即可。

【代码实现】

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>


using namespace std;

const int N = 1e5 + 10, M = 2 * N;
int h[N], e[M], ne[M], idx;
int d[N];// 统计入度情况
bool st[N];
int a[N];

int n;

void add(int a, int b)  // 添加一条边a->b
{
   
   
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}


void topsort()
{
   
   
    queue<int> q;
    for (int i = 1; i <= n; i ++ )
        if(d[a[i]] == 0)
            q.push(i);
    while(q.size())
    {
   
   
        auto t = q.front();
        q.pop();
        
        for(int i = h[t]; i != -1; i = ne[i])
        {
   
   
            int j = e[i];
            d[j] --;
            if(d[j] == 0)
                q.push(j);
        }
    }
}

// int dfs(int u, int father, int sum)
// {
   
   
//     if(st[u]) return cnt;
//     st[u] = true;
    
//     sum ++;
//     for(int i = h[u]; i != -1; i = ne[i])
//     {
   
   
//         int j = e[i];
//         if(j == father) continue;
//         return dfs(j, u, sum);
//     }
// }

// 下面这个dfs函数在acwing能过,蓝桥杯官网报的编译错误(我不理解)
int dfs(int u, int father)
{
   
   
    
    st[u] = true;

    int sum = 1;
    for(int i = h[u]; i != -1; i = ne[i])
    {
   
   
        int j = e[i];
        if(!st[j])
        {
   
   
            int s = dfs(j, u);
            sum += s;
        }
    }
    return sum;
}

int main()
{
   
   
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i ++ )
    {
   
   
        cin >> a[i];
        d[a[i]] ++;
        add(i, a[i]);
    }
    topsort();
    
    int ans = -1e8;
    for (int i = 1; i <= n; i ++ )
    {
   
   
        if(d[i] && !st[i])// 度不为0且没被访问过
        {
   
   
            int tmp = dfs(i, -1);
            // cout << tmp << endl;
            ans = max(ans, tmp);
        }
            
    }
    // puts("");
    cout << ans;
    
    return 0;
}

2.路径之迷(dfs + 路径打印)

【题目链接】https://www.lanqiao.cn/problems/89/learning/

搜索每一个由起点走到终点的所有路线,经过每一个位置时,给它的x、y都加上1的贡献,最后到达右下角时,如果x、y的值等于输入的箭靶的数目则为正确答案

【代码实现】

只得了一部分分数(40%)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>


using namespace std;

const int N = 25;
int g[N][N];
int rx[N], ry[N];
int nx[N], ny[N];
vector<int> path;
bool st[N][N];
bool is_find;
int n;

int dx[4] = {
   
   -1, 0, 1, 0}, dy[4] = {
   
   0, 1, 0, -1};


bool check()
{
   
   
    for (int i = 0; i < n; i ++ ) 
        if(rx[i] != nx[i] || ry[i] != ny[i]) 
            return false;
    return true;    
}

void dfs(int x, int y)
{
   
   
    if(is_find) return ;// 结束递归
    if(x == n - 1 && y == n - 1 && check())
    {
   
   
        // if(check())
        // {
   
   
            is_find = true;
            for (int i = 0; i < path.size(); i ++) cout << path[i] << ' ';
        // }    
        return ;    
    }
    for(int i = 0; i < 4; i ++)
    {
   
   
        int a = x + dx[i], b = y + dy[i];
        if(a < 0 || a >= n || b < 0 || b >= n) continue;
        if(st[a][b]) continue;
        
        st[a][b] = true;
        rx[a] ++;
        ry
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值