HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
生活随笔
收集整理的這篇文章主要介紹了
HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6203
題意:n+1 個點 n 條邊的樹(點標號 0 ~ n),有若干個點無法通行,導致 p 組 U V 無法連通。問無法通行的點最少有多少個。
解法:按照詢問的LCA深度排序,然后順序標記每個詢問的LCA。根據所給的樹(任意點為根)預處理出每個點的前序 DFS 序和后序 DFS 序(需統一標號),及點的深度。根據 p 組 U V 處理每組兩點的 LCA 。壓入優先隊列(LCA 深度大的點優先出隊)。對于出隊的 U V 及其對應的 LCA ,判斷點 U 或點 V 是否在之前已禁止的某點的子樹中,對于某點U如果在禁止通行的點P的子樹中,則L[P]<=L[U]<=R[U]<=R[P]一定成立。所以可以利用樹狀數組區間更新單點查詢,對于每個禁止通行點標記區間L[P],R[P]的所有節點。查詢的時候如果L[U]被標記,說明U,V已經被隔斷。
?
#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; }?
轉載于:https://www.cnblogs.com/spfa/p/7515837.html
總結
以上是生活随笔為你收集整理的HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv调pc摄像头拍摄图片
- 下一篇: 操作系统的“冷板凳”要坐多久?万字长文解