您的位置:首页 > 其它

HDU 6203 ping ping ping lca 线段树成段更新

2017-09-14 16:19 483 查看
题目链接:HDU 6203


ping ping ping

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 507    Accepted Submission(s): 128


Problem Description

The structure of the computer room in Northeastern University is pretty miraculous. There are n servers,
some servers connect to the gateway whose IP address is 0 directly. All servers are connected with each other by n netting
twines. It is said that this structure is favorable for maintaining physical problem of servers.

But because of an unexpected rainstorm, the computer room was destroyed by a terrible thunderclap!

Our maintainer Bittersweet found that many servers were not able to be visited, so he hurried to the computer room to lookup the reason. After several hours, Bittersweet realized that some net gape of servers were broken by thunderclap. However, there were
too many servers to find out all the broken net gapes quickly. So he came up with an idea to assess the damaged condition roughly. Bittersweet decided to turn on some servers and ping other servers randomly, then record the unsuccessful pairs of servers.

Now he need a program to analyze the record to confirm what is the minimum number
of servers whose net gape was destroyed by thunderclap. Can you help him to complete this work?

 

Input

There are at most 20 test cases.

In each test case, the first line is an integer n (3≤n≤104),
denoting the number of servers. The IP address of these servers is 1…n.

Then follows n lines,
each line contains two integers u and v (0≤u,v≤n),
denoting that the server whose IP address is u is
connected with the server whose IP address is v by
netting twine initially.

After those, there is one line contains only an integer p (p≤50000),
denoting the number that Bittersweet uses ping.

Then follows p lines,
each line contains two integers U and V ,
denoting when using server U to
ping server V,
it returned unsuccessful.

 

Output

A single integer x in
a line, denoting at least x servers
whose net gape were broken.

 

Sample Input

4
1 0
4 2
2 0
3 2
2
1 3
2 1

 

Sample Output

1

 

题意:

已知n+1个点从0到n,构成一棵树,现在有一些对节点ping不通,问最少会有几个节点坏掉。

题目分析:思路参考http://blog.csdn.net/DorMOUSENone/article/details/77929604

树状数组的区间维护没写过,所以节点信息我用线段树来维护。这里我们先预处理出来每一对节点的lca,然后按照lca由大至小排序,然后预处理出来每个点的dfs序in[]和后序的dfs序out[],这样如果点pos的节点坏掉了,其子树上的所有节点u都有in[pos]<in[u]<out[u]<out[pos]。由于每次处理lca深度深的点,所以每次查询u和v有没有被标记过,如果没有说明2个点到最近公共祖先的路径还没有坏,为了让每个坏点达到最大覆盖范围,所以贪心的认定是最近公共祖先的节点坏掉了,同时区间标记整个范围in[]~out[],同理,如果u和v两点任意一点已经被标记了,而它们的lca深度一定比之前的节点小,所以二者显然已经无法ping通。然后计数就好了。

dfs序标记和处理树,然后录入线段树,每次查询区间维护lazy。

//
// main.cpp
// HDU 6203 ping ping ping
//
// Created by teddywang on 2017/09/12.
// Copyright © 2017年 teddywang. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5;
const int inf=0x3f3f3f3f;
struct node{
int x,y,lca;
friend bool operator < (node a,node b)
{
return a.lca>b.lca;
}

}nodes[maxn];
int in[maxn],out[maxn],depth[maxn],order[maxn],tree[maxn];
int s,e,pos1,ans,n,m,cnt,mins,anspos;
bool lazy[maxn];
vector <int> edge[maxn];

void dfs1(int pos,int fa)
{
int len=edge[pos].size();
order[++cnt]=pos;
in[pos]=cnt;
for(int i=0;i<len;i++)
{
if(edge[pos][i]!=fa)
{
depth[ edge[pos][i] ]=depth[pos]+1;
dfs1(edge[pos][i],pos);
order[++cnt]=pos;
}
}
}

void dfs2(int pos,int fa)
{
int len=edge[pos].size();
in[pos]=++cnt;
for(int i=0;i<len;i++)
{
if(edge[pos][i]!=fa)
{
//in[edge[pos][i]]=++cnt;
dfs2(edge[pos][i],pos);
}
}
out[pos]=cnt;
}

void pushup1(int rt)
{
tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
}

void push_down2(int rt)
{
if(lazy[rt]==1)
lazy[rt<<1]=lazy[rt<<1|1]=1;
}

void build1(int l,int r,int rt)
{
if(l==r)
{
tree[rt]=depth[order[l]];
return ;
}
int mid=(l+r)>>1;
build1(l,mid,rt<<1);
build1(mid+1,r,rt<<1|1);
pushup1(rt);
}

void update2(int st,int ed,int l,int r,int rt)
{
if(l>ed||st>r) return;
if(st<=l&&r<=ed)
{
lazy[rt]=1;
return;
}
int mid=(l+r)>>1;
update2(st,ed,l,mid,rt<<1);
update2(st,ed,mid+1,r,rt<<1|1);
}

void query1(int st,int ed,int l,int r,int rt)
{
if(st>r||l>ed) return;
if(st<=l&&r<=ed)
{
if(tree[rt]>mins) return;
mins=tree[rt];
}
if(l==r)
{
anspos=l;
return;
}
int mid=(l+r)>>1;
query1(st,ed,l,mid,rt<<1);
query1(st,ed,mid+1,r,rt<<1|1);
}

int query2(int st,int ed,int l,int r,int rt)
{
if(st>r||l>ed) return 0;
if(l<=st&&ed<=r)
{
if(lazy[rt]) return 1;
}
if(l==r) return 0;
push_down2(rt);
int mid=(l+r)>>1;
return query2(st,ed,l,mid,rt<<1)||query2(st,ed,mid+1,r,rt<<1|1);
}

int main()
{
while(~scanf("%d",&n))
{
depth[0]=0;cnt=0;
for(int i=0;i<=n;i++)
edge[i].clear();
for(int i=0;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs1(0,-1);
build1(1,cnt,1);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
s=in[u],e=in[v],mins=inf;
if(s>e) swap(s,e);
query1(s,e,1,cnt,1);
nodes[i].x=u,nodes[i].y=v;
nodes[i].lca=order[anspos];
}
sort(nodes,nodes+m);
ans=0,cnt=0;
dfs2(0,-1);
memset(lazy,0,sizeof(lazy));
for(int i=0;i<m;i++)
{
s=e=in[nodes[i].x];
if(!query2(s,e,1,cnt,1))
{
s=e=in[nodes[i].y];
if(!query2(s,e,1,cnt,1))
{
ans++;
s=in[nodes[i].lca];
e=out[nodes[i].lca];
update2(s,e,1,cnt,1);
}
}
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: