DFS序

    科技2022-07-13  100

    DFS序

    重要性质:

    1.一个结点子树上的时间戳,一定大于这个节点的时间戳且连续 2.某些链上的时间戳也是连续的

    应用:

    把树强行搞成“连续的”,这样我们就可以套一个线段树,实现以下操作 1:把以x为节点的子树的所有节点都加上z(区间修改) 2:求以x为节点的子树的所有节点的和(区间求和) 预处理:生成线段树产生可依靠的数组xds[n];并且找出每一个节点的子树包含的子树(包含这个节点)。

    int k=0,xds[n],sum[n]; int DFS(int n,int fa) { xds[++k]=n; if(head[n]==0)return 1; int su=0; for(int i=head[n];i;i=edge[i].next) { int v=edge[i].to; if(v==fa)continue; int temp=DFS(v,u); su+=temp; } sum[n]=su+1; return sum[n]; }

    检验程序

    #include<bits/stdc++.h> using namespace std; #define mod 1e9+7 #define N 100005 #define inf 0x3f3f3f3f const double PI = atan(1.0)*4.0; typedef long long ll; struct edge { int next,to; }E[N]; int head[N]; int num,n; void chushi() { for(int i=1;i<=n;i++) head[i]=-1; } void add(int u,int v) { E[num].next=head[u]; E[num].to=v; head[u]=num++; } int k,xds[N],sum[N]; int DFS(int x,int fa) { xds[++k]=x; if(head[x]==0)return 1; int su=0; for(int i=head[x];~i;i=E[i].next) { int v=E[i].to; if(v==fa)continue; int temp=DFS(v,x); su+=temp; } sum[x]=su+1; return sum[x]; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); freopen("E:\\in.txt","r",stdin); cin>>n; chushi(); int x,y; for(int i=1;i<=n;i++) { cin>>x>>y; add(x,y); } DFS(1,0); for(int i=1;i<=n;i++) cout<<xds[i]<<" "; cout<<endl; for(int i=1;i<=n;i++) cout<<sum[i]<<" "; }

    但是dfs序无法处理以下问题

    1:从x结点到y结点最短路径上所有的节点的值都加上z 2:求x结点到y结点最短路径的所有节点的和 这时候我们就需要树链剖分

    Processed: 0.009, SQL: 8