zoukankan      html  css  js  c++  java
  • 【NOI题解】【bzoj题解】NOI2008 bzoj1063 道路设计

    @ACMLCZH学长出的毒瘤题T3。再也不是“善良”的出题人了。

    题意:bzoj

    题解:

    经典的树形DP题目,屡见不鲜了,然而我还是没有写出来。

    这一类的题目有很多,例如这里的C题

    主要套路是把对儿子的枚举变成一个类似背包的转移方式,实现降复杂度。

    需要注意的是某一个地方的DP值不能直接拿来判断是否有解,例如mod=1时,DP值全为0就没法判断了。

    这里比较骚的操作是把mod的倍数变成mod,而0不变,这样就不会漏判。

    #include<bits/stdc++.h>
    #define F(i,a,b) for(int i=a;i<=(b);++i)
    #define eF(i,u) for(int i=h[u];i;i=nxt[i])
    #define ll long long
    using namespace std;
    
    int n,mod;
    ll f[100001][21][3],g[100001][21][3];
    
    int h[100001],nxt[200001],to[200001],tot;
    inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;}
    
    inline ll M(ll x){return x?(x-1)%mod+1:0;}
    
    void DFS(int u,int fa){
    	int cnt=0;
    	eF(i,u) if(to[i]!=fa) DFS(to[i],u), ++cnt;
    	if(!cnt){
    		F(j,0,20) f[u][j][0]=1;
    		return;
    	}
    	F(j,0,20) f[u][j][0]=1;
    	eF(i,u) if(to[i]!=fa){
    		F(j,0,20){
    			g[u][j][0]=M(j?f[u][j][0]*(f[to[i]][j-1][0]+f[to[i]][j-1][1]+f[to[i]][j-1][2]):0);
    			g[u][j][1]=M(f[u][j][0]*(f[to[i]][j][0]+f[to[i]][j][1])+(j?f[u][j][1]*(f[to[i]][j-1][0]+f[to[i]][j-1][1]+f[to[i]][j-1][2]):0));
    			g[u][j][2]=M(f[u][j][1]*(f[to[i]][j][0]+f[to[i]][j][1])+(j?f[u][j][2]*(f[to[i]][j-1][0]+f[to[i]][j-1][1]+f[to[i]][j-1][2]):0));
    			f[u][j][0]=g[u][j][0];
    			f[u][j][1]=g[u][j][1];
    			f[u][j][2]=g[u][j][2];
    		}
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&mod);
    	int x,y; F(i,2,n) scanf("%d%d",&x,&y), ins(x,y), ins(y,x);
    	DFS(1,0);
    	F(j,0,20)
    		if(f[1][j][0]+f[1][j][1]+f[1][j][2]){
    			printf("%d
    %lld",j,(f[1][j][0]+f[1][j][1]+f[1][j][2])%mod);
    			break;
    		}
    	return 0;
    }
  • 相关阅读:
    hdu 1195 Open the Lock
    hdu 1180 诡异的楼梯
    hdu 1175 连连看
    背包(采药)
    LCS模板,求长度,并记录子串
    hdu 1159 Common Subsequence
    hdu 1231 最大连续子序列
    DP的简单应用
    hdu 1728 逃离迷宫
    点击页面其他地方,关闭弹框
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/8525356.html
Copyright © 2011-2022 走看看