zoukankan      html  css  js  c++  java
  • [笔记][题解]树形DP&lgP4084

    [笔记][题解]树形(DP)&(lgP4084)

    原题链

    题目分析

    一眼看过去是给定几个限制求方案数,那么肯定联想到(DP),而且给出的是树形结构,那么就是一道树形(DP)的题。

    树形(DP)

    那么先来总结一下树形(DP)的一般规律,首先关于状态转移方程,一般是设(dp[i][j])表示的是以(i)为根的子树,有(j)或者更多的限制就用多维数组。那么如何求解呢?一般考虑两种思路:(1.)先把所有的子树都搜索完再来更新父亲节点的信息(&)答案。(2.)而如果是树上背包问题,则需要一个一个的更新。

    例题(lgP4084)

    这道题很容易得出状态转移方程:设(dp[i][j])表示节点(i)涂第(j)种颜色的方案数,那么转移就从与它相连的颜色不同的点的(dp)值转移而来,注意如果某一个点已经被强制涂上了某种颜色,那么它的(dp)数组的值只有那一种颜色是(1),其他的都是(0),而对于没有染色的点来说初始值都是(1)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    struct node{
    	int to,next;
    }edge[100010 * 2];
    int fir[100010],tot;
    long long dp[100010][5];
    const int mod = 1e9 + 7;
    void add(int x,int y){
    	edge[++tot].to = y;
    	edge[tot].next = fir[x];
    	fir[x] = tot;
    }
    void dfs(int x,int fa){
    	for(int i = 1;i <= 3;i++){
    		if(dp[x][i]){
    			for(int j = 0;j < i;j++)
    				dp[x][j] = 0;
    			break; 
    		}
    		dp[x][i] = 1;
    	}
    	for(int i = fir[x];i;i = edge[i].next){
    		if(edge[i].to == fa)continue;
    		dfs(edge[i].to,x);
    		dp[x][1] = (dp[x][1] * (dp[edge[i].to][2] + dp[edge[i].to][3]) % mod) % mod;
    		dp[x][2] = (dp[x][2] * (dp[edge[i].to][1] + dp[edge[i].to][3]) % mod) % mod;
    		dp[x][3] = (dp[x][3] * (dp[edge[i].to][1] + dp[edge[i].to][2]) % mod) % mod;
    	}
    }
    int main(){
    	int n,m;
    	cin>>n>>m;
    	for(int i = 1;i < n;i++){
    		int x,y;
    		cin>>x>>y;
    		add(x,y);
    		add(y,x);
    	}
    	for(int i = 1;i <= m;i++){
    		int x,y;
    		cin>>x>>y;		
    		dp[x][y] = 1;
    	}
    	dfs(1,0);
    	cout<<(dp[1][1] + dp[1][2] + dp[1][3]) % mod<<endl; 
    	return 0;
    } 
    
  • 相关阅读:
    linux 文件权限(s、t、i、a)解析
    vim Vundle
    数据结构学习(1)
    Android ImageView设置图片原理(上)
    C++11 之auto
    Android屏幕分辨率获取方法--源码剖析
    C++的发展方向是对的嘛?
    c++ 的前世今生
    学习知识的一种思路
    遗失的访谈小评
  • 原文地址:https://www.cnblogs.com/czy--blog/p/14028106.html
Copyright © 2011-2022 走看看