HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6203
題意:n+1 個(gè)點(diǎn) n 條邊的樹(shù)(點(diǎn)標(biāo)號(hào) 0 ~ n),有若干個(gè)點(diǎn)無(wú)法通行,導(dǎo)致 p 組 U V 無(wú)法連通。問(wèn)無(wú)法通行的點(diǎn)最少有多少個(gè)。
解法:按照詢問(wèn)的LCA深度排序,然后順序標(biāo)記每個(gè)詢問(wèn)的LCA。根據(jù)所給的樹(shù)(任意點(diǎn)為根)預(yù)處理出每個(gè)點(diǎn)的前序 DFS 序和后序 DFS 序(需統(tǒng)一標(biāo)號(hào)),及點(diǎn)的深度。根據(jù) p 組 U V 處理每組兩點(diǎn)的 LCA 。壓入優(yōu)先隊(duì)列(LCA 深度大的點(diǎn)優(yōu)先出隊(duì))。對(duì)于出隊(duì)的 U V 及其對(duì)應(yīng)的 LCA ,判斷點(diǎn) U 或點(diǎn) V 是否在之前已禁止的某點(diǎn)的子樹(shù)中,對(duì)于某點(diǎn)U如果在禁止通行的點(diǎn)P的子樹(shù)中,則L[P]<=L[U]<=R[U]<=R[P]一定成立。所以可以利用樹(shù)狀數(shù)組區(qū)間更新單點(diǎn)查詢,對(duì)于每個(gè)禁止通行點(diǎn)標(biāo)記區(qū)間L[P],R[P]的所有節(jié)點(diǎn)。查詢的時(shí)候如果L[U]被標(biāo)記,說(shuō)明U,V已經(jīng)被隔斷。
?
#include <bits/stdc++.h> using namespace std; const int maxn = 20100; typedef long long LL; vector <int> G[maxn]; int n, m, dfsclk, c[maxn], fa[maxn][21], dep[maxn], L[maxn], R[maxn]; bool vis[maxn]; struct node{int u,v,uv;node(){}node(int u,int v,int uv):u(u),v(v),uv(uv){}bool operator<(const node &rhs)const{return dep[uv]<dep[rhs.uv];} }; void dfs(int x){vis[x]=1;L[x]=++dfsclk;for(int i=0; i<G[x].size(); i++){int v=G[x][i];if(!vis[v]){dep[v]=dep[x]+1;fa[v][0]=x;dfs(v);}}R[x]=++dfsclk; } void init(){for(int j=1; j<=20; j++)for(int i=1; i<=n; i++)fa[i][j] = fa[fa[i][j-1]][j-1]; } int LCA(int u, int v){if(dep[u]<dep[v]) swap(u,v);for(int i=20; i>=0; i--){if((dep[u]-dep[v])&(1<<i))u=fa[u][i];}if(u==v) return u;for(int i=20; i>=0; i--){if(fa[u][i]!=fa[v][i]){u=fa[u][i];v=fa[v][i];}}return fa[u][0]; } int lowbit(int x){return x&(-x); } void add(int x, int v){while(x<maxn){c[x]+=v;x+=lowbit(x);} } void update(int x, int y, int z){add(x, z);add(y+1, -z); } int query(int x){int ret=0;while(x>0){ret+=c[x];x-=lowbit(x);}return ret; } int main() {while(~scanf("%d", &n)){memset(c, 0, sizeof(c));memset(vis, 0, sizeof(vis));memset(dep, 0, sizeof(dep));for(int i=0; i<=n+1; i++) G[i].clear();for(int i=1; i<=n; i++){int u,v;scanf("%d %d", &u,&v);u++,v++;G[u].push_back(v);G[v].push_back(u);}n++;dfsclk = 0;dfs(1);init();priority_queue <node> q;scanf("%d", &m);while(m--){int u, v;scanf("%d %d", &u,&v);u++;v++;int uv = LCA(u, v);q.push(node(u,v,uv));}int ans=0;while(!q.empty()){node now = q.top();q.pop();int flag = query(L[now.u])+query(L[now.v]);if(flag==0){ans++;update(L[now.uv],R[now.uv],1);}}printf("%d\n", ans);}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/spfa/p/7515837.html
總結(jié)
以上是生活随笔為你收集整理的HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: opencv调pc摄像头拍摄图片
- 下一篇: laravel安装Debugbar调试器