Questions surface: https://www.cnblogs.com/Juve/articles/11598286.html
attack:
Dominator tree bare title?
What is a dominant tree look:
Question: We have a directed graph (ring that may have), set a node as a starting point s. Now we ask: starting from the starting point s, to a point p all paths must go through the X-point what { p }.
In other words, delete X { P } to any point in the X PI and its edges into the edge, so that s will not reach p.
For this problem, the construction of the dominant tree on it
Specific steps:
We bfs to achieve in the new tree, a node x to be able to connect to all lca its point on the original in a new tree
According to this idea, we use the topology, the new update of its parent node in the tree while subtracting a point of penetration of
If it becomes 0 degree, then the multiplication with lca way to add it to a new drawing
Built out of the tree, then the answer is to ask each lca lca all inquiries nodes in the new tree
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define re register using namespace std; const int MAXN=5e4+5; const int MAXM=1e5+5; int n,m,Q,k,ans=0,du[MAXN]; int to[MAXM<<1],nxt[MAXM<<1],pre[MAXN],cnt=0; inline void add(re int u,re int v){ ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; } int f[MAXN][22],deep[MAXN]; int LCA(int x,int y){ if(deep[x]<deep[y]) swap(x,y); int k=deep[x]-deep[y]; for(int i=0;i<=20;i++) if((1<<i)&k) x=f[x][i]; if(x==y) return x; for(int i=20;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } queue<int>q; void bfs(int st){ deep[st]=1; q.push(st); while(!q.empty()){ int x=q.front(); q.pop(); for(int i=pre[x];i;i=nxt[i]){ int y=to[i]; if(!f[y][0]) f[y][0]=x; else f[y][0]=LCA(f[y][0],x); f[y][0]=f[y][0]; deep[y]=deep[f[y][0]]+1; --du[y]; if(!du[y]){ q.push(y); for(int j=0;j<=20;++j){ if(f[y][j-1]) f[y][j]=f[f[y][j-1]][j-1]; } } } } } signed main(){ scanf("%d%d%d",&n,&m,&Q); for(int i=1,u,v;i<=m;++i){ scanf("%d%d",&u,&v); add(u,v);++du[v]; } bfs(1); while(Q--){ scanf("%d",&k); scanf("%d",&ans); for(int i=1,vi;i<k;++i){ scanf("%d",&vi); ans=LCA(ans,vi); } printf("%d\n",deep[ans]); } return 0; }
tree:
Simple tree dp?
Probability is teasing you
Set size [x] denotes the subtree size of x, DP [x] represents the first time to a desired number of times x, then:
$dp[x]=dp[fa]+2*(n-size[x])+1$
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define int long long using namespace std; const int MAXN=1e5+5; int n; int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0; void add(int u,int v){ ++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; } int siz[MAXN],dp[MAXN]; void dfs(int x,int fa){ siz[x]=1; for(int i=pre[x];i;i=nxt[i]){ int y=to[i]; if(y==fa) continue; dfs(y,x); siz[x]+=siz[y]; } } void DFS(int x,int fa){ for(int i=pre[x];i;i=nxt[i]){ int y=to[i]; if(y==fa) continue; dp[y]=dp[x]+2*(n-siz[y])-1; DFS(y,x); } } signed main(){ scanf("%lld",&n); for(int i=1,u,v;i<n;++i){ scanf("%lld%lld",&u,&v); add(u,v),add(v,u); } dfs(1,0); dp[1]=1; DFS(1,0); for(int i=1;i<=n;++i){ printf("%0.3lf\n",(double)dp[i]); } return 0; }