Codeforces Round #263 Appleman and Tree(트리 DP)

1931 단어 dpCodeforces
제목: 한 그루의 나무 노드가 흰색과 검은색으로 염색되었는데, 몇 가지 절단 방법으로 나누어진 모든 부분에 검은색 노드가 꼭 포함되었는지 물었다.
사고방식: 트리 DP.dp[u][0]는 이 노드를 포함하는 자수를 자른 후에 검은 노드가 하나도 없다는 것을 나타낸다. dp[u][1]는 이 노드를 포함하는 자수를 자른 후에 마침 검은 노드가 하나 있는 방법을 나타낸다.만약 이 노드가 검은색이라면 dp[u][0]는 0일 수밖에 없다.아들이 검은색이 있을 때는 아들과 잘라낼 수 있고, 아들이 검은색이 없을 때는 잘라내지 않는다.만약에 노드 u가 흰색이라면 이 노드가 있는 자수에 검은색을 가지게 하려면 이 검은색은 반드시 아들에게서 온 것이다.이 노드가 있는 노드가 검은색이 없도록 하려면 아들이 검은색이 없으면 자르지 않고 검은색이 있으면 자르세요.
상태 전환 방정식:
검은색 노드:
dp[u][1]=dp[u][1]*(dp[vv][1]+dp[vv][0])
흰색 노드:
            dp[u][1]=dp[u][1]*(dp[vv][1]+dp[vv][0])+dp[u][0]*dp[vv][1];             dp[u][0]=dp[u][0]*(dp[vv][0]+dp[vv][1]);
코드는 다음과 같습니다.
#include
#include
#include
using namespace std;

const int maxn=200005;
const int mod=1000000007;
typedef long long ll;

struct Edge
{
    int u,v,next;
}edge[maxn];

int tot;
int first[maxn];

int color[maxn];

void add(int uu,int vv)
{
    edge[tot].u=uu;
    edge[tot].v=vv;
    edge[tot].next=first[uu];
    first[uu]=tot++;
}

ll dp[maxn][2];

void dfs(int u,int fa)
{
    if(color[u])
    {
        dp[u][0]=0;
        dp[u][1]=1;
    }
    else
    {
        dp[u][1]=0;
        dp[u][0]=1;
    }
    for(int i=first[u];i!=-1;i=edge[i].next)
    {
        int vv=edge[i].v;
        if(vv==fa)continue;
        dfs(vv,u);
        if(color[u])
        {
            dp[u][1]=dp[u][1]*(dp[vv][1]+dp[vv][0])%mod;
        }
        else
        {
            dp[u][1]=dp[u][1]*(dp[vv][1]+dp[vv][0])%mod+dp[u][0]*dp[vv][1]%mod;
            dp[u][1]%=mod;
            dp[u][0]=dp[u][0]*(dp[vv][0]+dp[vv][1])%mod;
        }
    }
}

int main()
{
   // freopen("data.txt","r",stdin);
    tot=0;
    memset(first,-1,sizeof(first));
    int n;
    scanf("%d",&n);
    for(int i=0;i

좋은 웹페이지 즐겨찾기