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 (3n104), denoting the number of servers. The IP address of these servers is 1n.
Then follows n lines, each line contains two integers u and v (0u,vn), 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 (p50000), 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);
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章