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:\n",++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:\n",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\n",exp); }