zoukankan      html  css  js  c++  java
  • 【COGS 2434】 暗之链锁 树上差分+LCA

    差分就是把一个值拆成许多差的和如 1 2 4 6 9 那么 把这个东西拆成 1 1 2 2 3 就是了,当然也可以理解为对一个问题分解为多个子问题并对其进行操作来得到原问题的答案。

    树上差分就更玄妙了,它既可以把原问题拆成他到根节点的所有点,也可以拆成子树,拆成子树的话修改一个点影响的是他到根的路径上所有点,根据这个我们可以再加上LCA来解决许多问题。

    这道题:I. 我们可以看出我们可以把它转化成一棵有根树,那么两部分一定是一个子树和其他 II. 那些虚边,都是砍断实边之后的藕断丝连,至于如何计算在这个实边上附上的虚边我们只需把那些虚路径乎到实路径上,就是路径修改. 

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    #define MAXN 100010
    using namespace std;
    inline int read()
    {
        int sum=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
          sum=(sum<<1)+(sum<<3)+ch-'0';
          ch=getchar();
        }
        return sum;
    }
    int w[MAXN],n,m;
    int f[MAXN];
    struct VIA
    {
      int to,next;  
    }c[MAXN<<1],q[MAXN<<2];
    int head[MAXN],t,Head[MAXN],T;
    bool v[MAXN];
    inline void add(int x,int y)
    {
      c[++t].to=y;
      c[t].next=head[x];
      head[x]=t;
    }
    inline void Add(int x,int y)
    {
      q[++T].to=y;
      q[T].next=Head[x];
      Head[x]=T;
    }
    inline void Init()
    {
       n=read(),m=read();
       for(int i=1,x,y;i<n;++i)x=read(),y=read(),add(x,y),add(y,x);
       for(int i=1,x,y;i<=m;++i)
       {
         x=read(),y=read();
         if(x==y)continue;
         Add(x,y),++w[x],++w[y],Add(y,x);
       }
    }
    inline int find(int x)
    {
       return x==f[x]?x:(f[x]=find(f[x]));
    }
    void LCA(int x,int p)
    {
       f[x]=x;
       for(int i=head[x];i;i=c[i].next)
       if(c[i].to!=p)
       {
         LCA(c[i].to,x);
         f[c[i].to]=x;
       }
       v[x]=1;
       for(int i=Head[x];i;i=q[i].next)
        if(v[q[i].to])
         w[find(q[i].to)]-=2;
    }
    int ans;
    void dfs(int x)
    {
       v[x]=0;
       for(int i=head[x];i;i=c[i].next)
        if(v[c[i].to])
        {
          dfs(c[i].to);
          w[x]+=w[c[i].to];
        }
    }
    inline void work()
    {
       LCA(1,0);
       dfs(1);
       for(int i=2;i<=n;++i)
        if(w[i]==0) ans+=m;
        else if(w[i]==1) ++ans;
       printf("%d",ans);
    }
    int main()
    {
        Init();
        work();
        return 0;
    }
  • 相关阅读:
    给C# 2005提供VB2005特有的My命名空间!
    利用iTextSharp把DataTable导出为PDF和RTF(Rich Text Format)文件
    [非技术][小孩]色色的小孩
    中秋节快乐!
    SnipperImages(Silverlight DEMO)控件设计之Slider和ColorSlider
    IE8的Activities,WebSlices示例ie8.taobao.com
    Net框架中的设计模式之Builder(构造者)兼谈抽象工厂和composite模式
    DiscuzNT 商品交易插件设计之[线下交易流程]
    听“汉代风云”,看“晁错之死”
    [翻译] python Tutorial 之一
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7241827.html
Copyright © 2011-2022 走看看