dfs序与求子树子节点(染了色)的个数

https://blog.csdn.net/hpu2022/article/details/81910490

https://blog.csdn.net/qq_39670434/article/details/78425125

https://www.cnblogs.com/gj-Acit/p/3236843.html

https://blog.csdn.net/iamzky/article/details/18923587

void dfs(int u) {
    in[u] = ans;
    for(int i = 0; i < edge[u].size(); i++) {
        ans++;
        dfs(edge[u][i]);
    }
    out[u] = ans;
}
https://vjudge.net/contest/230809#status/xiayuyang/I/0/

 https://cn.vjudge.net/contest/209473#problem/D

该题给出前n个节点有多少个子节点,然后要很多次查询,看是否为父子关系。

用dfs序做,如果in[x] < in[y] && out[x] > out[y] 则x是y的父节点。用栈模拟来标记每个节点的in于out值。

https://www.cnblogs.com/zyb993963526/p/7301444.html

https://www.cnblogs.com/L-Excalibur/p/8511527.html#include<iostream>

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=20000000+5;

int n, m;
int start[maxn];
int c[maxn];
int in[maxn];
int out[maxn];

void dfs(int u)
{
    stack<int> S;
    int dfs_clock=0;
    in[u]=0;
    S.push(u);
    while(!S.empty())
    {
        int x=S.top();
        if(in[x])
        {
            out[x]=++dfs_clock;
            S.pop();
            continue;
//out值,标记玩就要pop该点。 }
in[x]=++dfs_clock; for(int i=start[x];i<start[x]+c[x];i++) { if(i<n) {in[i]=0;S.push(i);} else {in[i]=++dfs_clock;out[i]=++dfs_clock;}
//如果小于n则把该点push进去,相当于bfs,然后标记in值,如果大于n则进去就出来所以可以直接标号 } } }
int main() { //freopen("in.txt","r",stdin); int T; int kase=0; scanf("%d",&T); while(T--) { scanf("%d",&n); int s=1; for(int i=0;i<n;i++) { scanf("%d",&c[i]); start[i]=s; s+=c[i]; } dfs(0); printf("Case %d: ",++kase); int q; scanf("%d",&q); while(q--) { int u,v; scanf("%d%d",&u,&v); if(in[u]<in[v] && out[u]>in[v]) puts("Yes"); else puts("No"); } if(T) puts(""); } return 0; }
/* by Lstg */
/* 2018-03-05 21:02:03 */

#include<stdio.h>
#include<iostream>
#include<queue>
#define MAXN 20000005
using namespace std;

int dfn[MAXN],dfm[MAXN],stk[MAXN],n;
queue<int>g[300005];//这里太大就会RE

void _mydfs(int x){
    
    int top=0,num=1,y;
    dfn[x]=num++;
    stk[++top]=x;
    while(top){
        x=stk[top];
        if(x>n||g[x].empty()){/*先判断x的大小防RE和WA(有时溢出不会告诉你是RE,而会返回WA)*/
            dfm[x]=num++;
            top--;
        }
        else{
            y=g[x].front();
            g[x].pop();
            dfn[y]=num++;
            stk[++top]=y;
        }
    }
}

int main(){

    int T,tot,i,x,y;
    scanf("%d",&T);
    for(int cc=1;cc<=T;cc++){
        scanf("%d",&n);
        tot=0;
        
        for(i=0;i<n;i++){
            while(!g[i].empty())g[i].pop();
            scanf("%d",&x);
            while(x--)
                g[i].push(++tot);
        }
        _mydfs(0);
        printf("Case %d:
",cc);
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            if(dfn[x]<dfn[y]&&dfm[x]>dfm[y])
                puts("Yes");
            else puts("No");
        }
        if(cc!=T)putchar(10);
    }
    return 0;
}

 https://vjudge.net/contest/218179#problem/Q 求子树大小(染色的)

https://blog.csdn.net/baidu_19306071/article/details/52005557

#include <bits/stdc++.h>

using namespace std;
const int maxm = 2e5 + 10;
const int maxn = 2e5 + 10;
typedef long long ll;
struct Edges{
    int u,v;
}edge[maxm];
vector<int> G[maxn];

int cnt[maxn];
int dfs(int cur,int from){
    for(int i = 0 ; i < G[cur].size() ; i ++){
        int v = G[cur][i];
        if(v == from) continue;
        cnt[cur] += dfs(v,cur);
    }
    return cnt[cur];
}

int main (){
    int n,k;
    scanf("%d %d", &n,&k);
    for(int i = 1 ; i <= k*2 ; i ++){
        int tmp;
        scanf("%d", &tmp);
        cnt[tmp] = 1;
    }
    int cn = 0;
    for(int i = 0 ; i < n-1 ; i ++){
        int u,v;
        scanf("%d %d", &u,&v);
        edge[i].u = u;
        edge[i].v = v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,-1);
    ll exp = 0;
    for(int i = 0 ; i < n-1 ; i ++){
        Edges & e = edge[i];
        int tt = min(cnt[e.u],cnt[e.v]);
        int tmp = min(2*k-tt,tt);
        exp += tmp;
    }
    printf("%lld
",exp);
}
原文地址:https://www.cnblogs.com/downrainsun/p/10294329.html