您的位置:首页 > 其它

HDU 6203 ping ping ping (LCA + 树状数组, 2017 ACM/ICPC Asia Regional Shenyang Online)

2017-09-11 09:19 453 查看

Problem

n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组
U V
无法连通。问无法通行的点最少有多少个。

Idea

根据所给的树(任意点为根)预处理出每个点的前序 DFS 序和后序 DFS 序(需统一标号),及点的深度。

根据 p 组
U V
处理每组两点的 LCA 。压入优先队列(LCA 深度大的点优先出队)。

对于出队的
U V
及其对应的 LCA ,判断点 U 或点 V 是否在之前已禁止的某点的子树中。

判断点 U 或点 V 是否在之前已禁止的某点的子树中。

处理方式:由于之前已经处理出每个点的前后序 DFS 序 In[] 和 Out[] 。

对于某点 U 若在已禁止通行点 P 的子树中,则 In[P]≤In[U]≤Out[U]≤Out[P] 一定成立。

故利用树状数组区间更新单点查询。对每个禁止通行点 P ,标记区间 [In[P],Out[P]] 中所有点。查询时,若点 In[U] 被标记,则说明
U V
已经被隔断。

同时,由于优先处理 LCA 深度大的点,不会出现点 U V 同时在同一个被禁止通行点 P 的子树内。

若 U ,V 均不在被禁止的点在子树内,则禁止
U V
的 LCA 点,同时对答案贡献 +1 。

Code

#include<bits/stdc++.h>
using namespace std;
#define LL long long
vector <int> g[10100];
int father[10100][22]={0};
int depth[10100]={0};
int bin[20200];
int In[10100];
int Out[10100];
int n,m;
struct Node{
int u,v,uv;
Node(){}
Node(int _u,int _v,int _uv):u(_u),v(_v),uv(_uv){}
friend bool operator<(Node n1,Node n2){
return depth[n1.uv]<depth[n2.uv];
}
};
bool visit[10010]={false};
int root,cnt;
void dfs(int u){
int i;
visit[u]=true;
In[u]=++cnt;
for (i=0;i<g[u].size();i++){
int v=g[u][i];
if ( !visit[v] ){
depth[v]=depth[u]+1;
father[v][0]=u;
dfs(v);
}
}
Out[u]=++cnt;
}
void bz(){
int i,j;
for (j=1;j<=20;j++)
for (i=1;i<=n;i++)
father[i][j]=father[father[i][j-1]][j-1];
}
int LCA(int u,int v) {
if ( depth[u]<depth[v] ) {
int temp=u;
u=v;
v=temp;
}
int dc=depth[u]-depth[v];
int i;
for (i=0;i<=20;i++)
{
if ( (1<<i) & dc)
u=father[u][i];
}
if (u==v) return u;
for (i=20;i>=0;i--){
if (father[u][i]!=father[v][i])
{
u=father[u][i];
v=father[v][i];
}
}
u=father[u][0];
return u;
}
inline int lowbit(int x) {  return x & -x;  }
inline int sum(int x) {
int res = 0;
while(x)    res += bin[x],  x -= lowbit(x);;
return res;
}
inline void add(int x, int w) {
while(x < 20200)    bin[x] += w, x += lowbit(x);
}
inline int update(int x, int y, int w) {
add(x, w);  add(y+1, -w);
}
int main()
{
int u,v,p;
while(scanf("%d", &n)!=EOF) {
memset(bin,0,sizeof(bin));
memset(visit,0,sizeof(visit));
for(int i=0;i<=n+1;++i)
g[i].clear();
for(int i=1;i<=n;++i){
scanf("%d %d",&u,&v);
u++, v++;
g[u].push_back(v);
g[v].push_back(u);
}
n++;
cnt=0;
dfs(1);
bz();
scanf("%d",&p);
priority_queue<Node> q;
while(!q.empty())   q.pop();
Node tmp;
while(p--){
scanf("%d %d",&u,&v);
u++;    v++;
int uv=LCA(u,v);
tmp = Node(u,v,uv);
q.push(tmp);
}
int ans=0;
while(!q.empty()){
tmp=q.top();
q.pop();
int flg=sum(In[tmp.u])+sum(In[tmp.v]);
if(!flg){
ans++;
update(In[tmp.uv],Out[tmp.uv],1);
}
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐