zoukankan      html  css  js  c++  java
  • Dark的项链(树链剖分)

    P2272 - Dark的锁链

    Description

    无向图中有N个节点和两类边,一类边被称为主要边,而另一类被称为附加边。Dark有N – 1条主要边,并且Dark的任意两个节点之间都存在一条只由主要边构成的路径。另外,Dark还有M条附加边。
    你的任务是把Dark斩为不连通的两部分。一开始Dark的附加边都处于无敌状态,你只能选择一条主要边切断。一旦你切断了一条主要边,Dark就会进入防御模式,主要边会变为无敌的而附加边可以被切断。但是你的能力只能再切断Dark的一条附加边。现在你想要知道,一共有多少种方案可以击败Dark。注意,就算你第一步切断主要边之后就已经把Dark斩为两截,你也需要切断一条附加边才算击败了Dark。

    Input

    第一行包含两个整数N和M。
    之后N – 1行,每行包括两个整数A和B,表示A和B之间有一条主要边。
    之后M行以同样的格式给出附加边。

    Output

    输出一个整数表示答案。

    Sample Input

    4 1
    1 2
    2 3
    1 4
    3 4

    Sample Output

    3

    Hint

    对于20% 的数据,N≤100,M≤100。
    对于100% 的数据,N≤100 000,M≤200 000。数据保证答案不超过2^31– 1。

    Source

    树链剖分, LCA

    这个题是一个树剖的变形。

    对于一个点

    1.不被任何副边覆盖。answer+=m;

    2.被一条副边覆盖。只能断掉主边,再断掉这条副边,answer++;

    3.被多条副边覆盖。不能达到目的.

    附:用线段树写可能超时,可以差分记录被覆盖数目。

    注意!!!!!!!

    *:在跳到同一条重链上时,差分(id[min(deep[x],deep[y])]+1,deep[max(deep[x],deep[y])])

    (在最顶端时,非根节点有一条父边连向父亲,不要加);

    *:最后统计差分数组时,应当跳过根节点:

    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define MAXX 1000100
    using namespace std;
    struct data{
      int nxt,to;
    }edge[MAXX*2];
    int top[MAXX],head[MAXX],hson[MAXX],siz[MAXX],id[MAXX],w[MAXX],fa[MAXX],deep[MAXX];
    int n,fr,to,tot,m,sm,ans;
    void add(int f,int t){edge[++tot].nxt=head[f],head[f]=tot;edge[tot].to=t;}
    void dfs1(int num,int f){
      hson[num]=0;siz[num]=1;fa[num]=f;deep[num]=deep[f]+1;
      for(int i=head[num];i;i=edge[i].nxt)if(edge[i].to!=f){
          int too=edge[i].to;
          dfs1(too,num);
           siz[num]+=siz[too];
          if(siz[hson[num]]<siz[too])hson[num]=too;
        }
    }
    void dfs2(int num,int toop){
      top[num]=toop,id[num]=++sm;
      if(hson[num])dfs2(hson[num],toop);
      for(int i=head[num];i;i=edge[i].nxt)
      if(edge[i].to!=hson[num]&&edge[i].to!=fa[num])dfs2(edge[i].to,edge[i].to);
    }
    void update(int x,int y){w[x]++,w[y+1]--;}
    void ask(int x,int y){
      while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        update(id[top[x]],id[x]);
        x=fa[top[x]];
      }
      if(deep[x]>deep[y])swap(x,y);
      if(id[x]+1<=id[y])update(id[x]+1,id[y]);
    }
    int main(){
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      scanf("%d%d",&n,&m);
      for(int i=1;i<n;++i)scanf("%d%d",&fr,&to),add(fr,to),add(to,fr);
      dfs1(1,0),dfs2(1,1);
      for(int i=1;i<=m;++i)scanf("%d%d",&fr,&to),ask(fr,to);
      for(int i=2;i<=n;++i)w[i]+=w[i-1];
      for(int i=2;i<=n;++i)if(!w[i])ans+=m;else  if(!(w[i]-1))ans++;
      printf("%d",ans);
      return 0;
    }


  • 相关阅读:
    MySQL-基本sql命令
    Java for LeetCode 203 Remove Linked List Elements
    Java for LeetCode 202 Happy Number
    Java for LeetCode 201 Bitwise AND of Numbers Range
    Java for LeetCode 200 Number of Islands
    Java for LeetCode 199 Binary Tree Right Side View
    Java for LeetCode 198 House Robber
    Java for LeetCode 191 Number of 1 Bits
    Java for LeetCode 190 Reverse Bits
    Java for LeetCode 189 Rotate Array
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6501173.html
Copyright © 2011-2022 走看看