 MEDIUM

# PREREQUISITES:

Math, Trees, Probability, BFS, Data Structures, Graphs, Mathematics, Algorithms, Graph Algos, Traversals

# PROBLEM:

A Directed rooted tree is given. Hema is starting from the root node, it takes one second for her to go to any of the child nodes. Find the probability that Hema is on a given node K after a very long time. [Consider infinite time]

# QUICK EXPLANATION:

After infinite time, Hema will be present on any of the leaf nodes only. So, the probability that Hema is present on any of the internal nodes will be 0.

\textbf{Algorithm}:
Create the adjacency list for all the nodes present in the tree and find the parent of each node. Starting from node K, find the product of the number of child nodes for each of its ancestors. Reciprocate this result and print the answer.

\textbf{Pseudo-code}:

``````    ans = 1
node = k
while (node!=1)
{
node = par[node];
if (node == 1)
ans *= sizeof(adj[node]) // number of child nodes of root –> size of adj[node]
else
ans *= (sizeof(adj[node]) - 1)// number of child nodes–> size of adj[node]
// subtract 1 – because the parent of this node shouldn’t be considered.
}
print (1/ans)
``````

# EXPLANATION:

The nodes of a tree can be classified into 2 types. So, there are two cases:

\textbf{Case 1}: K is an internal node. In this case, print 0 as the answer. As time is infinite, Hema will never stop at a non-leaf node, it would’ve reached some leaf.

\textbf{Case 2}: K is a leaf node.
Here, we have to calculate the probability of choosing the ancestor of K at each level in the tree, and finally multiply all these probabilities to get the final result.

\textbf{Code}:

``````    #include "bits/stdc++.h"

using namespace std;

#define endl '\n'
#define rep(i, a, b, inc) for(long long i = a; i < b; i += inc)
#define REP(i, n) rep(i, 0, n, 1)
#define pb push_back
typedef long long ll;
typedef long double ld;

ll par[(ll)(1e6) + 1] = {0};
bool vis[(ll)(1e6) + 1];
void dfs(ll v)
{
vis[v] = 1;
{
if (!par[u])
par[u] = v;
if (!vis[u])
dfs(u);
}
}

ld solve(ll n)
{
ll k, u , v;
cin >> k;
REP(i, n - 1)
{
cin >> u >> v;
}
// Adjacency list stores all the neighbouring nodes of each of the nodes in the tree.
if (n == 1 && k == 1) return 1; // if there is only one node ( which is the root), Hema will stay on the same node after infinite time, hence the probability is 1.
if (adj[k].size() != 1 || k == 1) return 0; // Probability that Hema is present at the root node is 0 when the root has children.

dfs(1); // Perform dfs on the root node to find and store the parent of each node.
ll node = k, ans = 1;
while (node != 1) // starting from node k, traverse through each of its ancestors in the tree
{
node = par[node];
if (node == 1)
ans *= (adj[node].size());// number of child nodes of root –> size of adj[node]
else
ans *= (adj[node].size() - 1); )// number of child nodes –> size of adj[node]
// Subtract 1 - the parent of this node shouldn’t be considered.

}
return 1.0 / ans; // return the reciprocal of the product.
}

int main()
{
ld n, c;
cin >> n;
c = solve(n);
cout << fixed << setprecision(6) << c << endl; // round the answer to 6 decimal places
return 0;
}
``````

# SOLUTIONS:

Setter's Solution
``````    n,k=map(int,input().split())
g=[[] for _ in range(n)]
p=[-1]*n
for _ in range(n-1):
u,v=map(int,input().split())
g[u-1].append(v-1)
g[v-1].append(u-1)
p,q=1,
while len(q):
u=q.pop(0)
c=0
for v in g[u]:
c+=1 if p[v]==-1 else 0
for v in g[u]:
if p[v]==-1:
q.append(v)
p[v]=p[u]/c
if c>0:
p[u]=0
print(round(p[k-1],6))
``````
Tester's Solution
``````    def dfs(node,e,v,p,leaf):
v[node]=True
for i in e[node]:
if not v[i]:
p[i]=node
leaf[node]=False
dfs(i,e,v,p,leaf)

n,k=map(int,input().split())
e=[[]for i in range(n)]
for i in range(n-1):
u,v=map(int,input().split())
e[u-1].append(v-1)
e[v-1].append(u-1)
par=[-1 for i in range(n)]
vis=[False for i in range(n)]
leaf=[True for i in range(n)]
dfs(0,e,vis,par,leaf)
res=0
if leaf[k-1]:
node=par[k-1]
ans=1
while node!=-1:
if node==0:
ans=ans*(len(e[node]))
else:
ans=ans*(len(e[node])-1)
node=par[node]
res=1/ans
print('%.6f'%res)
``````
Editorialist's Solution
``````    #include "bits/stdc++.h"

using namespace std;

#define endl '\n'
#define rep(i, a, b, inc) for(long long i = a; i < b; i += inc)
#define REP(i, n) rep(i, 0, n, 1)
#define pb push_back
typedef long long ll;
typedef long double ld;

ll par[(ll)(1e6) + 1] = {0};
bool vis[(ll)(1e6) + 1];
void dfs(ll v)
{
vis[v] = 1;
{
if (!par[u])
par[u] = v;
if (!vis[u])
dfs(u);
}
}

ld solve(ll n)
{
ll k, u , v;
cin >> k;
REP(i, n - 1)
{
cin >> u >> v;
}
if (n == 1 && k == 1) return 1;
if (adj[k].size() != 1 || k == 1) return 0;

dfs(1);
ll node = k, ans = 1;
while (node != 1)
{
node = par[node];
if (node == 1)
else
}
return 1.0 / ans;
}

int main()
{
ld n, c;
cin >> n;
c = solve(n);
cout << fixed << setprecision(6) << c << endl;
return 0;
}
``````
1 Like