I was solving the Independent Set problem from Atcoder Educational DP Contest (P - Independent Set).
Some assumptions that I made to solve this problem: Any node can be taken as the root node of the tree and then the subtrees can be assigned unique root nodes (i.e. the children of the parent node act as the root nodes of the subtrees).
Approach: I thought of calculating the number of ways to color a subtree with root node j for all valid j, first after painting the parent node as white and then after painting the parent node as black. After that the number of ways to color the tree is the sum of the products of number of ways to color each subtree (whose parent node is the child of the parent node of the whole tree) in both the cases. Then the bases cases will be the ones where we are painting the leaf nodes. A leaf node can be painted either black or white if its parent is painted white and it can only be painted white if its parent node is painted black.
For example, if I have a tree like 1----0----2, and I take 0 as the root node, when I paint 0 with white, subtree with root node 1 can be painted in 2 ways and subtree with root node 2 can also be painted in 2 ways, so number of ways to paint the tree when root node 0 is painted white = 2x2 = 4. Now, if I paint 0 with black then first subtree can only be painted in one way, similarly second subtree can also be painted in only one way, so the number of ways to paint the tree when 0 is painted black = 1x1. Therefore, total number of ways to paint the tree is 4+1 = 5.
I tried to code the above approach using DFS, but it works only for three of the sample test cases, in other words it simply doesn’t work. Following is that code:
#include <bits/stdc++.h>
using namespace std;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define ll long long
const ll mod = 1e9 + 7;
const int maxn = 1e5 + 5;
ll degree[maxn] = {0};
int parent[maxn] = {-1};
bool color[maxn] = {false};
bool used[maxn] = {false};
ll dp[maxn] = {-1};
void addEdge(vector<int> adj[], int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
degree[u]++, degree[v]++;
}
ll dfs(int u, vector<int> adj[])
{
used[u] = true;
if(degree[u] == 1)
{
if(parent[u] != -1)
{
if(!color[parent[u]]) return 1;
else return 2;
}
}
if(dp[u] != -1) return dp[u];
color[u] = true;
ll ways = 0, p = 1;
for(int v : adj[u])
{
if(!used[v])
{
parent[v] = u;
p = (p*dfs(v,adj))%mod;
used[v] = false;
}
}
ways = (ways%mod + p%mod)%mod;
color[u] = false;
p = 1;
for(int v : adj[u])
{
if(!used[v])
{
p = (p*dfs(v,adj))%mod;
}
}
ways = (ways%mod + p%mod)%mod;
used[u] = false;
return dp[u] = ways;
}
int main()
{
FASTIO
int n, x, y;
cin >> n;
vector<int> adj[n];
for(int i=0; i<n-1; i++)
{
cin >> x >> y;
addEdge(adj,x-1,y-1);
}
dfs(0,adj);
cout << dp[0] << "\n";
return 0;
}
Is my approach correct? And if it is, then what changes should I make to the code? Any help is highly appreciated.