• #树形dp#nssl 1469 W



    分析

    首先一些结论,每条边最多被翻一次,而且由翻的边所构成的连通块答案就是度数为奇数的点的个数的一半,
    因为在连通块内必然选择两个叶子节点间的路径翻是最优的,所以也就是选择两个度数为奇数的点,所以结论很显然
    (dp[i][0/1])表示第(i)个点与其父亲的边翻或不翻时,以第(i)个点为根的子树的最小代价(操作数(x)和路径长度(y)
    (f[0/1])表示第(i)个点的儿子们是否影响第(i)个点的度数的最小代价(儿子们的答案之和)
    那么(f[0]=min {f[0]+dp[son][0],f[1]+dp[son][1]},f[1]=min{f[0]+dp[son][1],f[1]+dp[son][0]})
    考虑用(f[0],f[1])更新(dp[i][0/1]),那么(dp[i][0]=min{(f[1].x+1,f[1].y),f[0]},dp[i][1]=min{(f[1].x,f[1].y+1),(f[0].x+1,f[0].y+1)})
    最后输出(dp[1][0])


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstdlib>
    #define rr register
    using namespace std;
    const int inf=1e9,N=100011;
    struct rec{
    	int x,y;
    	rec operator +(const rec &t)const{
    	    return (rec){x+t.x,y+t.y};
    	}
    	bool operator <(const rec &t)const{
    	    return x<t.x||(x==t.x&&y<t.y);
    	}
    }dp[N][2];
    struct node{int y,w,next;}e[N<<1];
    int as[N],k=1,n;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline rec Min(rec x,rec y){return x<y?x:y;}
    inline void dfs(int x,int fa,int w){
    	rr rec f1=(rec){0,0},f2=(rec){inf,inf},F1,F2;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa){
    		dfs(e[i].y,x,e[i].w);
    		F1=Min(f1+dp[e[i].y][0],f2+dp[e[i].y][1]);
    		F2=Min(f1+dp[e[i].y][1],f2+dp[e[i].y][0]);
    		f1=F1,f2=F2;
    	}
    	if (w==1) dp[x][0]=(rec){inf,inf};
    	    else dp[x][0]=Min(f1,(rec){f2.x+1,f2.y});
    	if (w==0) dp[x][1]=(rec){inf,inf};
    	    else dp[x][1]=Min((rec){f1.x+1,f1.y+1},(rec){f2.x,f2.y+1});
    }
    signed main(){
    	n=iut();
    	for (rr int i=1;i<n;++i){
    	    rr int x=iut(),y=iut();
    		rr int z1=iut(),z2=iut();
    	    rr int z=z2==2?z2:(z1^z2);
    		e[++k]=(node){y,z,as[x]},as[x]=k;
    		e[++k]=(node){x,z,as[y]},as[y]=k;
    	}
    	dfs(1,0,0);
    	return !printf("%d %d",dp[1][0].x>>1,dp[1][0].y);
    }
    
  • 相关阅读:
    简单工厂设计模式
    MVC备忘
    在MVC后台代码中想实现删除时弹出"确认删除"效果
    集合
    嵌套
    整理 补课内容
    百鸡百钱
    ////输入一个100以内的数,判断是不是正整数;
    课后题 5 6
    课后题3,4
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13493191.html
Copyright © 2020-2023  润新知