zoukankan      html  css  js  c++  java
  • w

     dp

    题解

    首先第一问就是奇度点个数/2

    直接$dp$不好$dp$,考虑关于奇度点来设立

    边权下放到节点

    $f[x][0/1]$结构体定义,$f[x][0].c1$表示$x$与父亲连边不反转时奇度点个数,$f[x][0].c2$表示$x$与父亲连边翻转是要的最小操作数$f[x][1]$表示翻转

    转移就是分情况讨论,我们首先要将子树合并完,最后再上传到当前节点

    w1表示子树有一条边指向当前节点代价(奇度点个数为奇)

    w2表示子树没有边指向当前节点代价(奇度点个数为偶)

    分别转移

    $w1=min(w2+f[y][1],w1+f[y][0])$

    解释一下保证奇度点个数为奇可以是当前已考虑子树内两两合,并翻转当前这条边;或者已考虑子树内伸出一条边当前边不伸

    $w2=min(w1+f[y][1],w2+f[y][0])$

    和上面类似

    那么对于当前来说

    $f[x][0]$由两部分转移,可以是没操作$w2$可以当前点和子树一奇度点结合$c1=w1.c1+1,c2=w1.c2$(路径长度不+1是因为在下面统计过了)

    $f[x][1]$由两部分转移,可以是让子树伸的边继续延伸$c1=w1.c1,c2=w1.c2+1$可以是当前边翻转然后当前点成为奇点$c1=w2.c1+1,c2=w2.c2+1$

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define inf 1e9+7
    #define A 1111111
    ll head[A],nxt[A],ver[A],edg[A];
    ll tot,n;
    void add(ll x,ll y,ll opt){
        nxt[++tot]=head[x],head[x]=tot,ver[tot]=y,edg[tot]=opt;
    }
    struct node{
        ll c1,c2;
        node(){}
        node (const ll &a,const ll &b){
            c1=a,c2=b;
        }
        friend bool operator < (const node &a,const node &b){
            return (a.c1==b.c1)?(a.c2<b.c2):(a.c1<b.c1);
        }
        friend node operator +(const node &a,const node &b){
            node c;c.c1=0,c.c2=0;
            c.c1=a.c1+b.c1,c.c2=a.c2+b.c2;
            return c;
        }
    }f[A][2];
    void dfs(ll x,ll pre,ll opt){
        node w1(inf,inf),w2(0,0),n1,n2;
        for(ll i=head[x];i;i=nxt[i]){
            ll y=ver[i];
            if(y==pre) continue ;
            dfs(y,x,edg[i]);
            n1=min(w1+f[y][0],w2+f[y][1]);
            n2=min(w2+f[y][0],w1+f[y][1]);
            w1=n1,w2=n2;
        }
    //    printf("w1.c1=%lld w1.c2=%lld w2.c1=%lld w2.c2=%lld
    ",w1.c1,w1.c2,w2.c1,w2.c2);
        if(opt==2){
            f[x][1]=min(node(w1.c1,w1.c2+1),node(w2.c1+1,w2.c2+1));
            f[x][0]=min(node(w1.c1+1,w1.c2),node(w2.c1,w2.c2));
        }
        else if(opt==1){//must
            f[x][1]=min(node(w1.c1,w1.c2+1),node(w2.c1+1,w2.c2+1));
            f[x][0]=node(inf,inf);
        }
        else if(opt==0){//must`not
            f[x][0]=min(node(w1.c1+1,w1.c2),node(w2.c1,w2.c2));
            f[x][1]=node(inf,inf);
        }
    }
    int main(){
        scanf("%lld",&n);
        for(ll i=1;i<n;i++){
            ll x,y,opt,case1,case2;
            scanf("%lld%lld%lld%lld",&x,&y,&case1,&case2);
            if(case2==2){
                add(x,y,2);add(y,x,2);
            }
            else if(case1==case2){
                add(x,y,0);add(y,x,0);
            }
            else if(case1!=case2){
                add(x,y,1);add(y,x,1);
            }
        }
        dfs(1,0,0);
        printf("%lld %lld
    ",f[1][0].c1>>1,f[1][0].c2);
    }
    View Code
  • 相关阅读:
    mysql 位操作支持
    统计代码行数
    git merge的参数--squash的用处
    bash和zsh切换
    nginx 添加https支持
    查看Memcache运行状况
    unkown host mac 解决
    react-redux中的重要API解析
    js 同步延时调用
    从输入 URL 到浏览器渲染完成
  • 原文地址:https://www.cnblogs.com/znsbc-13/p/11616702.html
Copyright © 2011-2022 走看看