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;
    }


  • 相关阅读:
    在ASP.NET中使用FusionCharts图表
    IE 输入baidu就死掉
    以WebServices方式上传图片
    GUID System.Guid .
    记录一个静态类的静态属性
    [转]通用分页存储过程
    如何解决“呈现控件时出错”的问题
    C#中调用SQL存储过程(带输入输出参数的例子)
    Rose实例:构造银行业务模型[转]
    Mylove net 我们手里的金钱只是保持自由的一种工具!卢梭
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6501173.html
Copyright © 2011-2022 走看看