• 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;
    }
  • 相关阅读:
    Dev 控件笔记1 repositoryItemLookUpEdit 控件
    装饰账务管理
    Tiptop ERP 采购运费一键分摊
    笔记:两数互相交换,不使用第三方变量
    .net core3.0 webapi搭建(一)
    【笔记】冒泡排序
    Mysql 几种常见的插入 Insert into,Replace Into,Insert ignore
    【转】IEnumerable接口的一个简单示例
    [转]从实例谈OOP、工厂模式和重构
    浅谈C#委托的用法-delegate[转]
  • 原文地址:https://www.cnblogs.com/war1111/p/11237201.html
Copyright © 2020-2023  润新知