A. Tree Child Draws Trees

Problem - 1830A - Codeforces

Problem Description:

Copil Copac gets a n-1 given by n − 1nA list of 1 edges describing a tree ofnnA tree composed of n vertices. He decided to draw it using the following algorithm:

  • step 0 00 : draw the first vertex (vertex1 11 ). Go to step1 11
  • Step 1 11 : For each edge in the input, draw it in sequence: if this edge connects an already drawn vertexuuu and an undrawn vertexvvv , then draw the undrawn vertexvvv and this side. After checking each edge, go to step2 22
  • step 2 22 : If all vertices are drawn, terminate the algorithm. Otherwise, go to step1 11

The number of reads is defined as Copil Copac. Perform steps 1 11 times.

Please calculate the Copil Copac readings required to draw this tree.

Plug-in cf better

The problem is simplified: create trees and draw them in the order of tree creation. For the i-th edge, you can j > idraw the edge without consuming times, otherwise it will take one drawing. Ask how many times it takes to draw.

Idea: similar to tree-shaped dp.

Code:

#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <random>
#include <sstream>
#include <numeric>
#include <stdio.h>
#include <functional>
#include <bitset>
#include <algorithm>
using namespace std;

#define Multiple_groups_of_examples
#define IOS std::cout.tie(0);std::cin.tie(0)->sync_with_stdio(false);
#define dbgnb(a) std::cout << #a << " = " << a << '\n';
#define dbgtt cout<<" !!!test!!! "<<endl;
#define rep(i,x,n) for(int i = x; i <= n; i++)

#define all(x) (x).begin(),(x).end()
#define pb push_back
#define vf first
#define vs second

typedef long long LL;
typedef pair<int,int> PII;

const int INF = 0x3f3f3f3f;
const int N = 2e5 + 21;

void inpfile();
void solve() {
    
    
    int n; cin>>n;
    vector<vector<PII>> g(n+1); // PII({ 点u,输入顺序})
    for(int i = 2; i <= n ; ++i) {
    
    
        int u,v; cin>>u>>v;
        // 无向 
        g[u].push_back({
    
    v,i});
        g[v].push_back({
    
    u,i});
    }
    // f[i] 表示 到结点i用了多少个次数
    vector<int> f(n + 1);
    int ans = 0; // 记录答案
    f[1] = 1; // 第一个节点需要一次
    auto vis(f); // 是否走过,走过不走,也可以不用这个vis数组,因为 y == fu || idx == fi 就已经将这个判断过了(

    //  当前节点  当前节点的父亲节点  这个节点的边的输入顺序编号
    auto dfs = [&](auto &&dfs, int u, int fu, int fi) -> void {
    
    
        for(auto t: g[u]) {
    
    
            // 得到 儿子节点 和 <u,y> 边的编号
            int y = t.vf, idx = t.vs;
            if(y == fu || idx == fi) continue;
            if(vis[y]) continue;
            vis[y] = 1;
            // 如果 <u,y> 的输入编号 小于 <fu,u> 的输入编号则需要消耗次数
            f[y] = f[u] + (idx < fi);
            dfs(dfs, y,u,idx);
        }
        // 更新答案,肯定最大的,因为题要求是全部绘制完需要的次数
        ans = max(ans, f[u]);
    };
    dfs(dfs,1,-1,0);
    cout<<ans<<endl;
}
int main()
{
    
    
    #ifdef Multiple_groups_of_examples
    int T; cin>>T;
    while(T--)
    #endif
    solve();
    return 0;
}
void inpfile() {
    
    
    #define mytest
    #ifdef mytest
    freopen("ANSWER.txt", "w",stdout);
    #endif
}

Guess you like

Origin blog.csdn.net/qq_63432403/article/details/132631845