zoukankan      html  css  js  c++  java
  • poj3417

    poj3417
    lca+差分
    每加入一条新边就会形成一个环,这个环上除了新边都会被覆盖一次,断掉覆盖一次的边再断了覆盖它的新边就能把树分成两部分。对于被覆盖数大于1次的边,就得至少断两条新边,对答案就没有贡献了。对于没有被覆盖的,对答案贡献为新边的数量,覆盖为1的,贡献为1,再否则为0。
    d[x]表示节点x到其父亲节点的那条边被覆盖的次数,对于树根要特判

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cmath>
    #include<ctime>
    #include<set>
    #include<map>
    #include<stack>
    #include<cstring>
    #define inf 2147483647
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson ls,nl,mid,l,r
    #define rson rs,mid+1,nr,l,r
    #define N 100010
    #define For(i,a,b) for(int i=a;i<=b;i++)
    #define p(a) putchar(a)
    #define g() getchar()
    
    using namespace std;
    
    int n,m,x,y,ans;
    int s,f[N][21],deep[N];
    int d[N];
    
    struct node{
        int n;
        node *next;
    }*e[N];
    
    void in(int &x){
        int y=1;
        char c=g();x=0;
        while(c<'0'||c>'9'){
            if(c=='-')y=-1;
            c=g();
        }
        while(c<='9'&&c>='0'){
            x=(x<<1)+(x<<3)+c-'0';c=g();
        }
        x*=y;
    }
    void o(int x){
        if(x<0){
            p('-');
            x=-x;
        }
        if(x>9)o(x/10);
        p(x%10+'0');
    }
    
    void push(int x,int y){
        node *p;
        p=new node();
        p->n=y;
        if(e[x]==0)
            e[x]=p;
        else{
            p->next=e[x]->next;
            e[x]->next=p;
        }
    }
    
    void build(int now){
        deep[now]=deep[f[now][0]]+1;
        for(int i=1;(1<<i)<=deep[now];i++)
            f[now][i]=f[f[now][i-1]][i-1];
        for(node *i=e[now];i;i=i->next){
            if(i->n!=f[now][0]){
                f[i->n][0]=now;
                build(i->n);
            }
        }
    }
    
    int lca(int x,int y){
        if(deep[x]<deep[y])
            swap(x,y);
        int c=deep[x]-deep[y];
        For(i,0,log2(c))
            if((1<<i)&c)
                x=f[x][i];
        if(x==y)
            return x;
        for(int i=log2(deep[x]);i>=0;i--)
            if(f[x][i]!=f[y][i]){
                x=f[x][i];
                y=f[y][i];
            }
        return f[x][0];
    }
    
    int dfs(int x,int fa){
        for(node *i=e[x];i;i=i->next)
            if(i->n!=fa)
                d[x]+=dfs(i->n,x);
        return d[x];
    }
    
    int main(){
        in(n);in(m);
        For(i,1,n-1){
            in(x);in(y);
            push(x,y);
            push(y,x);
        }
        f[1][0]=1;
        build(1);
        For(i,1,m){
            in(x);in(y);
            d[x]+=1;d[y]+=1;
            d[lca(x,y)]-=2;
        }
        d[1]=dfs(1,1);
        For(i,1,n)
            if(!d[i]&&i!=1)
                ans+=m;
            else
                if(d[i]==1)
                    ans++;
        o(ans);
        return 0;
    }
  • 相关阅读:
    Win7中隐藏的上帝模式——GodMode
    C# 中有关 using 关键字
    数据结构 实验三  二叉树
    数据结构 实验二 栈
    指针知识(六):指针的指针
    指针知识(五):指针(pointer)和常量(const)
    指针知识(四):指针数学计算
    指针知识(三):指针与数组
    指针知识(二):指针初始化
    指针知识(一):指针声明
  • 原文地址:https://www.cnblogs.com/war1111/p/11237201.html
Copyright © 2011-2022 走看看