In Minimize Travel Tax DSA Interview Problem If we could determine the number of trips in which we pay the tax for some node, we can estimate the contribution of the node in the sum. We can do this using the idea of prefix sums on tree. Now that we can reduce the taxes for nodes that are not adjacent, we can use dynamic programming to solve this subproblem and calculate the required answer.

Let’s first the actual problem and then try to solve the problem together

## Minimize Travel Tax DSA Interview Problem

There are

$n$ cities connected by

$n-1$ bi-directional roads such that all the cities are connected.

You go on

$m$ trips where on the

$i-th$ trip you travel from city

${u}_{i}$ to city

${v}_{i}$. All the trips are independent of each other. You have to pay a tax of

$ta{x}_{i}$ on entering or leaving the

$i-th$ city. If you pay the tax while entering then you don’t need to pay at the time of leaving.

You can choose some non-adjacent cities and make their tax half. What can be the minimum sum of taxes you pay for all the

$m$ trips?

The first line contains a single integer

$t$

$(1\le t\le {10}^{4})$ — the number of test cases. The description of

$t$ testcase follows.

The first line of each testcase contains two integers

$n$ and

$m$

$(1\le n,m\le {10}^{5})$ — the number of nodes and the number of trips. The nodes are numbered

$1,2,\dots ,n$.

The second line contains

$n$ space separated integers

$ta{x}_{1},ta{x}_{2},...ta{x}_{n}$

$(2\le ta{x}_{i}\le {10}^{9};\phantom{\rule{2pt}{0ex}}ta{x}_{i}\mathrm{\%}2==0)$ denoting the taxes at the nodes of the tree.

The next

$n-1$ lines describe the tree. Each contains two space separated integers

$u$ and

$v$

$(1\le u,v\le n;u\ne v\phantom{\rule{1pt}{0ex}})$ denoting an edge between vertices

$u$ and

$v$. It is guaranteed that these edges form a tree.

Finally, there are

$m$ lines describing the trips. Each line contains two integers

$u$ and

$v$

$(1\le u,v\le n;u\ne v\phantom{\rule{1pt}{0ex}})$ denoting a trip from city to

$u$ to city

$v$.

It is guaranteed that the sum of

$n$ and

$m$ over all test cases does not exceed

${10}^{5}$ each.

For each testcase, print a single integer — the minimum sum of taxes you pay for all the trips in a single line.

2 3 2 2 2 8 1 2 1 3 1 3 3 2 3 2 2 4 2 1 2 2 3 1 3 1 2

13 10

- For trip 1, from 1 to 3: you will have to pay taxes at cities 1 and 3.
- For trip 2, from 3 to 2: you will have to pay taxes at cities 1,2 and 3.

You can reduce the taxes at cities 2 and 3. Then the net tax will be

$2\times 2+1\times 1+4\times 2=13$.So,the ans is

$13$.

- For trip 1, from 1 to 3: you will have to pay taxes at cities 1, 2 and 3.
- For trip 2, from 1 to 2: you will have to pay taxes at cities 1 and 2.

You can reduce the taxes at city 2. Then the net tax udll be

$2\times 2+2\times 2+2\times 1=10$. So,the ans is

$10$.

## Minimize Travel Tax Solution in C++

```
#include <bits/stdc++.h>
using namespace std;
void dfs(long long src,long long dis,long long p,vector<long long> adj[],vector<vector<long long>> &dp,vector<long long> &h)
{
h[src]=dis;
for(auto x: adj[src])
{
if(x!=p)
{
dp[x][0]=src;
dfs(x,dis+1,src,adj,dp,h);
}
}
}
long long kanc(long long x,long long k,vector<vector<long long>> &dp)
{
long long step=0;
long long node=x;
while(k!=0)
{
if(k%2)
{
node=dp[node][step];
if(node==0)
return 0;
}
k/=2;
step++;
}
return node;
}
long long lca(long long n1,long long n2,vector<long long> &h,vector<vector<long long>> &dp)
{
long long diff=abs(h[n1]-h[n2]);
if(h[n1]>h[n2])
{
n1=kanc(n1,diff,dp);
}
else
{
n2=kanc(n2,diff,dp);
}
if(n1==n2)
return n1;
long long jump=h[n1];
while(jump!=0)
{
long long v1=kanc(n1,jump,dp);
long long v2=kanc(n2,jump,dp);
if(v1==v2)
jump/=2;
else
{
n1=v1;
n2=v2;
}
}
return dp[n1][0];
}
long long dfs2(long long src,long long p,vector<long long> adj[],vector<long long> ×)
{
for(auto x:adj[src])
{
if(x!=p)
{
times[src]+=dfs2(x,src,adj,times);
}
}
return times[src];
}
long long cost(long long src,long long p,vector<long long> adj[],long long reduce,vector<long long> &tax,vector<vector<long long>> &d)
{
if(d[src][reduce]!=-1)
return d[src][reduce];
long long ans;
if(reduce)
{
ans=tax[src]/2;
}
else
{
ans=tax[src];
}
for(auto x: adj[src])
{
if(x!=p)
{
if(reduce)
ans+=cost(x,src,adj,0,tax,d);
else
ans+=min(cost(x,src,adj,0,tax,d),cost(x,src,adj,1,tax,d));
}
}
return d[src][reduce]=ans;
}
int main() {
long long t;
cin>>t;
while(t--)
{
long long n,m;
cin>>n>>m;
vector<long long> tax(n+1);
for(long long i=1;i<=n;i++)
cin>>tax[i];
vector<long long> adj[n+1];
for(long long i=1;i<n;i++)
{
long long u,v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
vector<vector<long long>> dp(n+1,vector<long long>(18,0));
vector<long long> h(n+1);
dfs(1,0,0,adj,dp,h);
for(long long j=1;j<=17;j++)
{
for(long long i=1;i<=n;i++)
dp[i][j]=dp[dp[i][j-1]][j-1];
}
vector<long long> times(n+1,0);
while(m--)
{
long long x,y;
cin>>x>>y;
long long z=lca(x,y,h,dp);
times[x]+=1;
times[y]+=1;
times[z]-=1;
times[dp[z][0]]-=1;
}
dfs2(1,0,adj,times);
for(long long i=1;i<=n;i++)
tax[i]*=times[i];
vector<vector<long long>> d(n+1,vector<long long>(2,-1));
cout<<min(cost(1,0,adj,0,tax,d),cost(1,0,adj,1,tax,d))<<endl;
}
return 0;
}
```

## 1 Comment