• 树形dp


    这里是主要的公式,可以这样理解:所有点到父亲节点u的距离和sall[u]已经算出来了,
    那么算v这个节点的时候,不在v子树范围内的点到v的距离都多了1,
    所以加上n-sz[v],v的子树的点到v的距离都减少了1,所以要减去sz[v].

    题意:

    给一棵树,然后有Q次询问,每次询问给你两个点,问你加一条边之后,这两个点所在的简单环的期望长度是多少

    简单环即这两个点在一个环上,这个环是没有重边的。

    solution:

    两个点u,v,只有3种情况

    1.lca(u,v)=v;

    这种情况的答案等于v上面的点的距离和除以v上面的点数量+u下面的点距离和除以u下面的点数。

    2.lca(u,v)=u;

    同上

    3.lca(u,v)!=u!=v

    这种情况的答案等于v下面的点的距离和除以v下面的点的数量+u下面的点的距离和除以v下面的点的数量。

    下面的点的距离和,这个东西,用树形dp去解决就好了。

    至于上面的点的距离和,假设lca(u,v)=v这种情况,那么sumUp[v]=sumAll[v]-sumDown[z]-sz[z],z点是v到u的那条路径上的v的儿子。

    sumAll[i]是所有点到i点的距离和,sz是这棵子树的大小,sumDown[i]是子树的距离和。

    然后这道题就结束了。

      1 /*************************************************************************
      2     > File Name: 树形dp.cpp
      3     > Author: QWX
      4     > Mail: 
      5     > Created Time: 2018/11/6 17:43:14
      6  ************************************************************************/
      7 
      8 
      9 //{{{ #include
     10 //#include<iostream>
     11 #include<cstdio>
     12 #include<algorithm>
     13 #include<iomanip>
     14 #include<vector>
     15 #include<cmath>
     16 #include<queue>
     17 #include<map>
     18 #include<set>
     19 #include<string>
     20 #include<cstring>
     21 #include<complex>
     22 #include<cassert>
     23 //#include<bits/stdc++.h>
     24 #define vi vector<int>
     25 #define pii pair<int,int>
     26 #define mp make_pair
     27 #define pb push_back
     28 #define fi first
     29 #define se second
     30 #define pw(x) (1ll << (x))
     31 #define sz(x) ((int)(x).size())
     32 #define all(x) (x).begin(),(x).end()
     33 #define rep(i,l,r) for(int i=(l);i<(r);i++)
     34 #define per(i,r,l) for(int i=(r);i>=(l);i--)
     35 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
     36 #define cl(a,b) memset(a,b,sizeof(a))
     37 #define fastio ios::sync_with_stdio(false);cin.tie(0);
     38 #define lson l , mid , ls
     39 #define rson mid + 1 , r , rs
     40 #define INF 0x3f3f3f3f
     41 #define LINF 0x3f3f3f3f3f3f3f3f
     42 #define ll long long
     43 #define ull unsigned long long
     44 #define dd(x) cout << #x << " = " << (x) << "," 
     45 #define de(x) cout << #x << " = " << (x) << "
    " 
     46 #define endl "
    "
     47 using namespace std;
     48 //}}}
     49 
     50 
     51 const int N=1e5+7;
     52 int n,m;
     53 int siz[N],fa[N][25],dep[N];
     54 ll sdown[N],sall[N];
     55 vi G[N];
     56 
     57 void dfs(int u,int f)
     58 {
     59     siz[u]=1;
     60     sdown[u]=0;
     61     for(auto v:G[u]){
     62         if(v==f)continue;
     63         dep[v]=dep[u]+1;
     64         fa[v][0]=u;
     65 //        dd(v),de(fa[v][0]);
     66         dfs(v,u);
     67         siz[u]+=siz[v];
     68         sdown[u]+=sdown[v]+siz[v];
     69     }
     70 }
     71 void dfs2(int u,int f)
     72 {
     73     for(auto v:G[u]){
     74         if(v==f)continue;
     75         sall[v]=sall[u]+n-2*siz[v];
     76         //这里是主要的公式,可以这样理解:所有点到父亲节点u的距离和sall[u]已经算出来了,
     77         //那么算v这个节点的时候,不在v子树范围内的点到v的距离都多了1,    
     78         //所以加上n-sz[v],v的子树的点到v的距离都减少了1,所以要减去sz[v].
     79         dfs2(v,u);    
     80     }
     81                 
     82 }
     83 int up(int u,int d)
     84 {
     85     per(i,20,0)if(d&(1<<i))u=fa[u][i];
     86     return u;
     87 }
     88 int LCA(int u,int v)
     89 {
     90     if(dep[u]<dep[v])swap(u,v);
     91     u=up(u,dep[u]-dep[v]);
     92     if(u==v)return u;
     93     per(i,20,0)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
     94 //    dd(u);de(fa[u][0]);
     95 //    dd(v);de(fa[v][0]); 
     96     return fa[u][0];
     97 }
     98 void Init()
     99 {
    100     dfs(1,-1);
    101     sall[1]=sdown[1];
    102     dfs2(1,-1);
    103     FOR(j,1,20)FOR(i,1,n)fa[i][j]=fa[fa[i][j-1]][j-1];
    104 //    FOR(i,1,5)dd(i),de(fa[i][0]);
    105 }
    106 int main()
    107 {
    108     scanf("%d%d",&n,&m); 
    109     rep(i,0,n-1){
    110         int a,b; scanf("%d%d",&a,&b);
    111         G[a].pb(b);
    112         G[b].pb(a);    
    113     }
    114     Init();
    115     rep(i,0,m){
    116         int u,v;scanf("%d%d",&u,&v);
    117         int lca=LCA(u,v);
    118 //        de(lca);
    119         double ans=dep[u]+dep[v]-2*dep[lca]+1;
    120         if(lca==u)swap(u,v);
    121         if(lca==v){
    122             int v2=up(u,dep[u]-dep[v]-1);
    123 //            de(v2);
    124 //              de(sall[2]);
    125             double supv=sall[v]-sdown[v2]-siz[v2];
    126 //            dd(sall[v]),dd(sdown[v2]),de(siz[v2]);
    127             ans+=1.0*supv/(n-siz[v2])+1.0*sdown[u]/siz[u];
    128         }else ans+=1.0*sdown[u]/siz[u]+1.0*sdown[v]/siz[v];
    129         printf("%.10f
    ",ans);
    130     }
    131 }
    View Code
  • 相关阅读:
    【C++ STL】List
    【C++ STL】Deques
    【C++ STL】Vector
    【C++ STL】容器概要
    linux shell读取配置文件
    【C++对象模型】第六章 执行期语意学
    【C++对象模型】第五章 构造、解构、拷贝 语意学
    【C++对象模型】第四章 Function 语意学
    【C++对象模型】第三章 Data语义学
    [翻译]解读CSS中的长度单位
  • 原文地址:https://www.cnblogs.com/klaycf/p/9918233.html
Copyright © 2020-2023  润新知