zoukankan      html  css  js  c++  java
  • 2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest G Gangsters in Central City lca、dfs序

    G . Gangsters in Central City

    题意: 一棵树1为根结点,点1 是水源,其它叶子结点是村庄。 q 个询问,每次询问有强盗入侵或离开某个村庄,要求输出两个数 ans1,ans2。 ans1表示最少要切断多少条边,使得强盗入侵的村庄与点1 不连通; ans2表示在确定了 ans1 的基础上,最少有多少个村庄没有被强盗入侵但又不与点1 连通。

    tags: 把点1 的所有儿子结点所拥有的子树单独圈出来,每次更新就在这个村庄所在的儿子结点的子树上操作即可。 按 dfs 序标出,每次只要看这个儿子标点上 dfs 序最小和最大的点。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 100005;
    
    int n, q, cnt, id[N], in[N], pi[N], Size[N];
    struct Edge { int to, next; } e[N<<2];
    vector< int > Son;
    set< int > se[N];
    int tot, head[N];
    void Addedge(int u, int v) {
        e[tot] = (Edge){ v, head[u] };  head[u]=tot++;
    }
    
    int dep[N], p[N][30];
    void dfslca(int u, int fa)
    {
        dep[u]=dep[fa]+1,  p[u][0]=fa;
        for(int i=head[u], to; to=e[i].to, ~i; i=e[i].next)
            if(to!=fa)   dfslca(to, u);
    }
    void Initlca()
    {
        mes(p, -1);  mes(dep, 0);  dep[0]=-1;
        dfslca(1, 0);
        for(int j=1; (1<<j)<=n; ++j)
            rep(i,1,n)  if(p[i][j-1]!=-1)
                p[i][j] = p[p[i][j-1]][j-1];
    }
    int Lca(int a, int b)
    {
        int i, j;
        if(dep[a] < dep[b]) swap(a, b);
        for(i=0; (1<<i)<=dep[a]; ++i) ;   --i;
        for(j=i; j>=0; --j)
            if(dep[a]-(1<<j) >= dep[b])
                a = p[a][j];
        if(a==b) return a;
        for(j=i; j>=0; --j)
            if(p[a][j]!=-1 && p[a][j]!=p[b][j])
                a=p[a][j], b=p[b][j];
        return p[a][0];
    }
    
    int dfs(int u, int fa, int son_id)
    {
        if(fa==1) {
            Son.PB(u);
            son_id = Son.size()-1;
        }
        in[u]=++cnt,  id[cnt]=u,  pi[u]=son_id;
        bool flag = true;
        for(int i=head[u], to; to=e[i].to, ~i; i=e[i].next)
            if(to!=fa)  Size[u] += dfs(to, u, son_id), flag=false;
        return Size[u] += (flag==true);
    }
    int get(int x)
    {
        if(se[x].size()==0) return 0;
        int l = *se[x].begin(),  r = *(--se[x].end());
        l = id[l],  r = id[r];
        int lca = Lca(l, r);
        return Size[lca] - se[x].size();
    }
    int main()
    {
        freopen("gangsters.in","r",stdin); freopen("gangsters.out","w",stdout);
        mes(head, -1);
        scanf("%d%d", &n, &q);
        int pii;
        rep(i,2,n) {
            scanf("%d", &pii);
            Addedge(pii, i);  Addedge(i, pii);
        }
        Initlca();
        Son.PB(0);
        dfs(1, 0, 0);
        int ans1=0, ans2=0, v, tmp1, tmp2;
        char  ch;
        while(q--)
        {
            scanf("%*c%c %d", &ch, &v);
            tmp1 = get(pi[v]);
            if(ch=='+') {
                if(se[pi[v]].size()==0) ++ans1;
                se[pi[v]].insert(in[v]);
            }
            else {
                if(se[pi[v]].size()==1) --ans1;
                se[pi[v]].erase(in[v]);
            }
            tmp2 = get(pi[v]);
            ans2 = ans2 - tmp1 + tmp2;
            printf("%d %d
    ", ans1, ans2);
        }
    
        return 0;
    }
    /*
    7 6
    1 2 1 3 3 3
    + 4
    + 5
    + 6
    + 7
    - 6
    - 5
    */
  • 相关阅读:
    ●BZOJ 3894 文理分科
    ●BZOJ 1797 [Ahoi2009]Mincut 最小割
    ●BZOJ 1934 [Shoi2007]Vote 善意的投票
    ●BZOJ 3996 [TJOI2015]线性代数
    php--->self与static区别
    php--->使用callable强制指定回调类型
    php--->依赖注入(DI)实现控制反转(IOC)
    php--->cookie和session
    php--->注册模式
    linux---> siege压力测试工具使用
  • 原文地址:https://www.cnblogs.com/sbfhy/p/7860972.html
Copyright © 2011-2022 走看看