HDU 6203 ping ping ping(贪心+LCA+DFS序+BIT)

ping ping ping

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 207    Accepted Submission(s): 47

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

 

题目链接:HDU 6203

题意就是求最少的点覆盖所有给定的q条路径,其实可以转换一下,就是求最多的路径集合使得集合内的路径两两之间不存在交点,那么跟HDU 4912是一样的题目了,先把所有路径按照其LCA深度从大到小排,即先处理靠下方的,因为这样对其他路径影响肯定是最小的,然后看这条路径的两端$u$和$v$是否被标记过,如果没标记就把以$LCA(u,v)$为根的子树全部标记上,否则就说明这条路径至少与其他路径存在一个交点(被标记的点)以此类推,如何快速标记子树呢?DFS序啊,而且子树是区间更新,查询端点是点查询,用BIT刚刚好

代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 10010;
const int M = 50010;
struct edge
{
    int to, nxt;
    edge() {}
    edge(int _to, int _nxt): to(_to), nxt(_nxt) {}
} E[N << 1];
int head[N], tot;
struct info
{
    int u, v, lca, dep;
    bool operator<(const info &rhs)const
    {
        return dep > rhs.dep;
    }
} node[M];
int D[N << 1], F[N], ver[N << 1], dp[N << 1][19], ts, dep[N];
int T[N], L[N], R[N], idx;

void init()
{
    CLR(head, -1);
    tot = 0;
    ts = 0;
    CLR(T, 0);
    idx = 0;
}
inline void add(int s, int t)
{
    E[tot] = edge(t, head[s]);
    head[s] = tot++;
}
void dfs(int u, int f, int d)
{
    ver[++ts] = u;
    D[ts] = d;
    F[u] = ts;

    L[u] = ++idx;
    dep[u] = d;
    for (int i = head[u]; ~i; i = E[i].nxt)
    {
        int v = E[i].to;
        if (v != f)
        {
            dfs(v, u, d + 1);
            ver[++ts] = u;
            D[ts] = d;
        }
    }
    R[u] = idx;
}
void RMQ_init(int l, int r)
{
    int i, j;
    for (i = l; i <= r; ++i)
        dp[i][0] = i;
    for (j = 1; l + (1 << j) - 1 <= r; ++j)
    {
        for (i = l; i + (1 << j) - 1 <= r; ++i)
        {
            int a = dp[i][j - 1], b = dp[i + (1 << (j - 1))][j - 1];
            dp[i][j] = D[a] < D[b] ? a : b;
        }
    }
}
int LCA(int u, int v)
{
    int l = F[u], r = F[v];
    if (l > r)
        swap(l, r);
    int len = r - l + 1;
    int k = 0;
    while (1 << (k + 1) <= len)
        ++k;
    int a = dp[l][k], b = dp[r - (1 << k) + 1][k];
    return D[a] < D[b] ? ver[a] : ver[b];
}
namespace BIT
{
    void add(int k, int v)
    {
        while (k < N)
        {
            T[k] += v;
            k += (k & -k);
        }
    }
    int sum(int k)
    {
        int ret = 0;
        while (k)
        {
            ret += T[k];
            k -= (k & -k);
        }
        return ret;
    }
}
int main(void)
{
    int n, u, v, i, q;
    while (~scanf("%d", &n))
    {
        init();
        for (i = 0; i < n; ++i)
        {
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        dfs(0, -1, 0);
        RMQ_init(1, ts);
        scanf("%d", &q);
        for (i = 0; i < q; ++i)
        {
            scanf("%d%d", &node[i].u, &node[i].v);
            node[i].lca = LCA(node[i].u, node[i].v);
            node[i].dep = dep[node[i].lca];
        }
        sort(node, node + q);
        int ans = 0;
        for (i = 0; i < q; ++i)
        {
            if (BIT::sum(L[node[i].u]) || BIT::sum(L[node[i].v]))
                continue;
            BIT::add(L[node[i].lca], 1);
            BIT::add(R[node[i].lca] + 1, -1);
            ++ans;
        }
        printf("%d\n", ans);
    }
    return 0;
}
posted @ 2017-09-11 11:01  Blackops  阅读(381)  评论(0编辑  收藏  举报