HDU 6203 ping ping ping lca 线段树成段更新
生活随笔
收集整理的這篇文章主要介紹了
HDU 6203 ping ping ping lca 线段树成段更新
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接: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);} }
總結
以上是生活随笔為你收集整理的HDU 6203 ping ping ping lca 线段树成段更新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows虚拟wifi配置
- 下一篇: 使用spring boot实现一个简单的