Copil Copac Draws Trees

3 篇文章 0 订阅

传送门

题意

思路

前提:建树用的是 vector<PII> v[N]  代表着 u:{v1,i} {v2,i} {v3,i}  i为编号,u->v是一条边

我们先假设把这颗树建完

令f[u]代表u节点需要经历多少次这样

之后dfs它们,观察它们出现的次序,如果v比u先出现就得 f[v] = f[u] + 1 否则 f[v] = f[u]

最后输出最大的f就行

代码

// https://codeforces.com/problemset/problem/1900/C  **1300**
// 复杂度应该是O(n) 判断只有左边和右边需要加return否则复杂度爆炸
#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define ft first
#define sd second
#define int long long
//#define i8 __int128
#define endl '\n'
#define ull unsigned long long
using namespace std;
typedef long long ll;
const double pi = acos(-1.0); //圆周率
const int mod = 1e9 + 7;
const int INF = 1e18;
const int N = 2e5 + 10;
typedef pair<int, int> PII;
int n;
string st;
void solve()
{
    cin >> n >> st;
    st = " " + st;
    vector<PII> ve(n+1);
    int x,y;
    for(int i = 1;i <= n;i ++)
    {
        cin >> x >> y;
        ve[i] = {x,y};
    }
    int minid = INF;
    auto dfs = [&] (auto dfs,int u,int cnt) -> void
    {   
        if(ve[u].first == 0 && ve[u].second == 0) 
        {
            minid = min(minid,cnt);
            return;
        }
        // 如果出现U 
        if(st[u] == 'U')
        {
            // 就有什么走什么
            if(ve[u].first != 0)
            {
                dfs(dfs,ve[u].first,cnt + 1);
            }
            if(ve[u].second != 0)
            {
                dfs(dfs,ve[u].second,cnt + 1);
            }
        }
        // 只能在左边走
        if(ve[u].first != 0 && st[u] == 'R' && ve[u].second == 0)
        {
            dfs(dfs,ve[u].first,cnt + 1);
            return;
        }
        // 只能在右边走
        if(ve[u].second != 0 && st[u] == 'L' && ve[u].first == 0)
        {
            dfs(dfs,ve[u].second,cnt + 1);
            return;
        }
        // 左右都能走
        if(ve[u].first != 0 || ve[u].second != 0)
        {
            // 如果必须往左走 
            if(st[u] == 'L')
            {   // 原来free  有改动+1
                if(ve[u].first != 0) dfs(dfs,ve[u].first,cnt);
                if(ve[u].second != 0) dfs(dfs,ve[u].second,cnt + 1);
            }
            if(st[u] == 'R')
            {   // 同上
                if (ve[u].second != 0) dfs(dfs,ve[u].second,cnt);
                if (ve[u].first != 0) dfs(dfs,ve[u].first,cnt + 1);
            }
        }
    };
    dfs(dfs,1,0);
    cout << minid << endl;
}
signed main()
{
    IOS;
    int _ = 1; cin >> _;
    while (_--) solve();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值