Gym 101142G : Gangsters in Central City(DFS序+LCA+set)

题意:现在有一棵树,1号节点是水源,叶子节点是村庄,现在有些怪兽会占领一些村庄(即只占领叶子节点),现在要割去一些边,使得怪兽到不了水源。给出怪兽占领和离开的情况,现在要割每次回答最小的割,使得怪兽不与1号节点有联系,而且满足被阻隔的村庄最少。输出最小割与组少的被误伤的村庄。

思路:把与一号节点相邻的点看作祖先gfa,然后它们自己作为树的根节点,根节点保存了子树里叶子节点的个数。很显然一棵树我们要割的是这棵树里所有怪兽的LCA与父亲边。子数里所有怪兽的LCA=LCA(最小DFS序的怪兽点,最大DFS序的怪兽点),用set维护有序关系即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
vector<int>G[maxn];  set<int>S[maxn];
int dfn[maxn],pos[maxn],fa[maxn][20],gfa[maxn],dep[maxn];
int sz[maxn],son[maxn],cut[maxn],num[maxn],times;
void dfs(int u,int f,int two)
{
    dfn[u]=++times; pos[times]=u;  dep[u]=dep[f]+1;
    if(dep[u]==2) two=u; if(two) gfa[u]=two;
    for(int i=0;i<G[u].size();i++)
      if(G[u][i]!=f)
        dfs(G[u][i],u,two),son[u]+=sz[G[u][i]];
    if(!son[u]) sz[u]=1;
    else sz[u]=son[u];
}
int LCA(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int i=18;i>=0;i--) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
    if(u==v) return u;
    for(int i=18;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
int ans1,ans2; int tmp[maxn];
int main()
{
    freopen("gangsters.in","r",stdin);
    freopen("gangsters.out","w",stdout);
    int N,Q,i,j;
    scanf("%d%d",&N,&Q);
    for(i=2;i<=N;i++){
        scanf("%d",&fa[i][0]);
        G[fa[i][0]].push_back(i);
    }
    for(i=1;i<=18;i++)
     for(j=1;j<=N;j++)
      fa[j][i]=fa[fa[j][i-1]][i-1];
    dfs(1,0,0);
    char opt[10]; int x;
    while(Q--){
        scanf("%s%d",opt+1,&x);
        int t=gfa[x];
        if(opt[1]==‘+‘){
            if(S[t].empty()) ans1++;
            else ans2-=tmp[t];
            S[t].insert(dfn[x]);
            int Lca=LCA(pos[*S[t].begin()],pos[*S[t].rbegin()]);
            cut[t]=Lca; num[t]++;
            tmp[t]=(sz[cut[t]]-num[t]);
            ans2+=tmp[t];
        }
        else {
            ans2-=tmp[t]; tmp[t]=0;
            S[t].erase(dfn[x]); num[t]--;
            if(S[t].empty()) ans1--,cut[t]=0;
            else {
                int Lca=LCA(pos[*S[t].begin()],pos[*S[t].rbegin()]);
                cut[t]=Lca; tmp[t]=(sz[cut[t]]-num[t]);
                ans2+=tmp[t];
            }
        }
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/9457780.html

时间: 2024-10-30 12:27:21

Gym 101142G : Gangsters in Central City(DFS序+LCA+set)的相关文章

2016 NEERC, Northern Subregional Contest G.Gangsters in Central City(LCA)

G.Gangsters in Central City 题意:一棵树,节点1为根,是水源.水顺着边流至叶子.该树的每个叶子上有房子.有q个询问,一种为房子u被强盗入侵,另一种为强盗撤离房子u.对于每个询问,要求给出最小的阀门数来阻断水流向强盗所在房子,且在阀门数最小的情况下求最小的误伤房子数(即没被入侵却被断水的房子). 思路:观察可发现,与根相连的子树都是独立的,因此有每有一颗这样的子树里有强盗,则ans1++,每有一颗这样的子树强盗全部撤离则ans1--:因此要维护的是误伤数ans2,我们对

G. Gangsters in Central City

给出一棵$1$为根节点的含$n$个节点的树,叶子节点都是房屋,在一个集合里面添加房屋和移除房屋. 每一次添加和移除后,回答下面两个问题. 1.  使得已选房屋都不能从根节点到达,最少需要砍多少条边. 2.  在第$1$问最少砍去边的条件下,如何砍边使得从节点点开始走不能到达的非已选房屋数目最小,输出最小值. 对于100%的数据 , $2 ≤ n ≤ 10^5 , 1 ≤ q ≤ 10^5$ Solution : 首先观察到,第一问的答案. 非常容易证明的一个上边界是砍去所有合法的$u$和1的连边

HDU 6203 ping ping ping(dfs序+LCA+树状数组)

http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连通.问无法通行的点最少有多少个. 思路: 贪心思维,破坏两个点的LCA是最佳的.那么怎么判断现在在(u,v)之间的路径上有没有被破坏的点呢,如果没有的话那么此时就要破坏这个lca点.一开始我们要把询问按照u和v的lca深度从大到小排序,如果某个点需要被破坏,那么它的所有子节点都可以不再需要破坏别的点

POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beauti

HDU 3966 dfs序+LCA+树状数组

题目意思很明白: 给你一棵有n个节点的树,对树有下列操作: I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k Q a 查询节点a的权值 数据大小 节点个数 n[1,50000], 操作次数 op[0,30000]; 不会树链剖分 故只有想其他的方法. 这道题有点类似今年上海网络赛的1003 ,不过那题我没做: 算法思路: 以节点1 为根,求出节点i 的 dfs序列 tim[i][2]; 其中tim[i][0

BZOJ 2819 Nim 树链剖分/DFS序+LCA+树状数组

题意:给定一棵树,每个节点是一堆石子,给定两种操作: 1.改变x号节点的石子数量 2.用从x到y的路径上的所有堆石子玩一次Nim游戏,询问是否有必胜策略 Nim游戏有必胜策略的充要条件是所有堆的石子数异或起来不为零 这题首先一看就是树链剖分 然后题目很善良地告诉我们深搜会爆栈 于是我们可以选择广搜版的树链剖分 BFS序从左到右是深搜,从右到左是回溯,一遍BFS就够 单点修改区间查询还可以套用ZKW线段树 不过这题其实不用这么麻烦 有更简单的办法 详见 http://dzy493941464.is

bzoj 2819 Nim(BIT,dfs序,LCA)

2819: Nim Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1596  Solved: 597[Submit][Status][Discuss] Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略的.于是vfleaking决定写一个玩Nim游戏的平台来坑玩家. 为了设计漂亮一点的

K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)

题目链接:http://codeforces.com/gym/101466/problem/K 题目: 题意: 给你一棵有n个节点的树,根节点始终为0,有两种操作: 1.RAND:查询以u为根节点的子树上的所有节点的权值的乘积x,及x的因数个数. 2.SEED:将节点u的权值乘以x. 思路: 比赛时少看了因数不大于13这句话,然后本题难度增加数倍,肝了两个小时都没肝出来,对不起队友啊,今天的组队训练赛实力背锅…… 这题一眼线段树,由于是对一棵子树进行处理,因此我们采用常规套路,借助dfs序将子树

2016-5-21 letwetell Round3 (百度之星初赛,dfs序)

halfapri(- o -)Y { 1.2016百度之星Round2A 题目链接 题解链接 1001 All X 循环节 1002 Sitting in Line 状压dp 1003 Snacks 1004 D Game 1005 BD String 找规律 1006 Gym Class 贪心+topo 2.2012多校第7场 hdu4366 Successor 线段树 + dfs序 }