• P3621 【[APIO2007]风铃】


    这个故事告诉我们,万物皆可暴(du)力(liu)dp。
    首先,题目的大意就是让我们通过他给定的一些变换方式使得这棵树变为完全二叉树。我们把完全二叉树所有的叶子节点连起来,应该只有两种情况,一种是一条链,另一种是两条链,其中一条链上的点的深度比另一条链的深度大1。
    令dp(i,j)表示i节点状态为j时的最小移动次数。
    状态无非三种:
    1.一条较深的链。
    2.一条较浅的链。
    3.两条链。
    我们注意到,对于一个点,不管怎么移动,深度总是不变,所以对于状态1和状态2,不需要向下递归,只需要查看这棵子树内所有的叶子节点的深度是否为对应值就可以了。

    第三种情况的转移就是下面六种情况:
    1.1+2
    2.1+3
    3.3+2
    4.2+1(+1)
    5.3+1(+1)
    6.2+3(+1)加一指的是左右子树交换的花费

    代码在下面:

    #pragma GCC optimize("Ofast,fast-math")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("O2")
    #include<bits/stdc++.h>
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,1<<17,stdin),pa==pb)?EOF:*pa++
    static char buf[1<<17],*pa(buf),*pb(buf);
    inline int read() {
    	register int s=0,f=1;
    	register char ch(gc);
    	while(ch<'0'||ch>'9') ch=='-'?f=-1,ch=gc:ch=gc;
    	while(ch>='0'&&ch<='9') s=s*10+ch-48,ch=gc;
    	return s*f;
    }
    using namespace std;
    struct yuansu {
    	int x,y;
    } bian[200005];
    int minn(10000000);
    int b[100005],dui[100005],deepth[100005];
    int lef[100005],rig[100005];
    int f(1);
    int n,x,y;
    int possible[100005][2];
    int cmp(yuansu a,yuansu b) {
    	return a.x<b.x;
    }
    int min(int a,int b) {
    	return a<b?a:b;
    }
    int bfs() {
    	int head(1),tail(2);
    	b[0]=b[1]=1;
    	dui[1]=1;
    	while(head!=tail) {
    		int i(dui[head]);
    		if(!lef[i]) {
    			if(minn!=10000000) {
    				if((minn>deepth[dui[head]]+1)||(minn<deepth[dui[head]]-1))return 1;
    			}
    			if(minn!=deepth[dui[head]]&&minn!=10000000)f=0;
    			minn=min(minn,deepth[dui[head]]);
    		}
    		if(!rig[i]) {
    			if(minn!=10000000) {
    				if((minn>deepth[dui[head]]+1)||(minn<deepth[dui[head]]-1))return 1;
    			}
    			if(minn!=deepth[dui[head]]&&minn!=10000000)f=0;
    			minn=min(minn,deepth[dui[head]]);
    		}
    		if(!b[lef[i]]) {
    			dui[tail]=lef[i];
    			deepth[dui[tail]]=deepth[dui[head]]+1;
    			tail++;
    		}
    		if(!b[rig[i]]) {
    			dui[tail]=rig[i];
    			deepth[dui[tail]]=deepth[dui[head]]+1;
    			tail++;
    		}
    		head++;
    	}
    	return 0;
    }
    void dfs(int dian) {
    	if(!lef[dian]) {
    		if(deepth[dian]==minn)
    			possible[dian][0]=1;//若该点为浅点,则包含该点的子树不可能出现深状态(也就是0状态)
    		else
    			possible[dian][1]=1;
    	}
    	if(!rig[dian]) {
    		if(deepth[dian]==minn)
    			possible[dian][0]=1;
    		else
    			possible[dian][1]=1;
    	}
    	if(lef[dian]) {
    		dfs(lef[dian]);
    		possible[dian][0]|=possible[lef[dian]][0];
    		possible[dian][1]|=possible[lef[dian]][1];
    	}
    	if(rig[dian]) {
    		dfs(rig[dian]);
    		possible[dian][0]|=possible[rig[dian]][0];
    		possible[dian][1]|=possible[rig[dian]][1];
    	}
    	return;
    }
    void chushihua() {
    	dfs(1);
    	return;
    }
    int violence_dp(int dian,int zt) {
    	if(zt==0||zt==1) {
    		if(!possible[dian][zt])return 0;
    		else return 100000000;
    	} else {
    		int ans(100000000);
    		if(lef[dian]==0&&rig[dian]==0)return 100000000;
    		else if(!lef[dian]&&rig[dian]) {
    			if(deepth[dian]==minn) {
    				ans=min(ans,violence_dp(rig[dian],0)+1);//1+0 (+1)
    				ans=min(ans,violence_dp(rig[dian],2)+1);//1+2 (+1)
    			} else {
    				ans=min(ans,violence_dp(rig[dian],1));//0+1
    				ans=min(ans,violence_dp(rig[dian],2));//0+2
    			}
    		} else if(lef[dian]&&!rig[dian]) {
    			if(deepth[dian]==minn) {
    				ans=min(ans,violence_dp(lef[dian],0));//0+1
    				ans=min(ans,violence_dp(lef[dian],2));//2+1
    			} else {
    				ans=min(ans,violence_dp(lef[dian],1)+1);//1+0 (+1)
    				ans=min(ans,violence_dp(lef[dian],2)+1);//2+0 (+1)
    			}
    		} else {
    			ans=min(ans,violence_dp(lef[dian],0)+violence_dp(rig[dian],1));//0+1
    			ans=min(ans,violence_dp(lef[dian],2)+violence_dp(rig[dian],1));//2+1
    			ans=min(ans,violence_dp(lef[dian],0)+violence_dp(rig[dian],2));//0+2
    			ans=min(ans,violence_dp(lef[dian],1)+violence_dp(rig[dian],0)+1);//1+0 (+1)
    			ans=min(ans,violence_dp(lef[dian],1)+violence_dp(rig[dian],2)+1);//1+2 (+1)
    			ans=min(ans,violence_dp(lef[dian],2)+violence_dp(rig[dian],0)+1);//2+0 (+1)
    		}
    		return ans;
    	}
    }
    int main() {
    	freopen("mobiles.in","r",stdin);
    	freopen("mobiles.out","w",stdout);
    	n=read();
    	for(int i=1; i<=n; i++) {
    		x=read();
    		y=read();
    		if(x>0) {
    			lef[i]=x;
    		}
    		if(y>0) {
    			rig[i]=y;
    		}
    	}
    	if(bfs()) {
    		cout<<-1;
    		return 0;
    	}
    	chushihua();
    	if(f) {//判断是不是一颗满二叉树
    		cout<<0;
    		return 0;
    	}
    	if(violence_dp(1,2)>10000000)cout<<-1;
    	else cout<<violence_dp(1,2);
    	return 0;
    }
    


        }
        chushihua();
        if(f) {//判断是不是一颗满二叉树
            cout<<0;
            return 0;
        }
        if(violence_dp(1,2)>10000000)cout<<-1;
        else cout<<violence_dp(1,2);
        return 0;
    }

  • 相关阅读:
    tyflow birth节点
    tyflow雨滴在物体上滑落测试
    【bootstrap】如何在js中动态修改提示冒泡(Tooltips)的显示内容
    解决office自动更新失败,错误代码0xc0000142
    hosts文件路径(Windows)
    【微信测试版】支持安卓平板和手机同时登录
    【javascript】canvas画布涂鸦及保存图片到本地
    【python】图片批量压缩(多线程)
    【python】提取pdf文件中的所有图片
    【python】计算程序运行所消耗的总时间
  • 原文地址:https://www.cnblogs.com/thedreammaker/p/10986448.html
Copyright © 2020-2023  润新知