#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>

typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;

typedef std::vector<int> vector_int_t;
typedef std::string string8_t;

class TurnOnLampsDmitriyH
{ 
    struct road_t 
	{ 
		road_t(): to(0), id(0), isImp(0) {} 
		road_t(size_t to_, size_t id_, uint32_t isImp_): to(to_), id(id_), isImp(isImp_) {} 

		size_t to; 
		size_t id; 
		uint32_t isImp; 
	}; 

	typedef std::vector<road_t> vector_road_t; 
	typedef std::vector<vector_road_t> vector_2d_road_t; 
	typedef std::vector<uint64_t> vector_uint64_t; 
	typedef std::vector<vector_uint64_t> vector_2d_uint64_t; 
	typedef std::set<uint64_t> set_uint64_t; 

	void Walk(const vector_2d_road_t& links, const string8_t& isImportant, vector_int_t& wasHere, const size_t initialId, const size_t startId, const uint64_t currentChain, vector_2d_uint64_t& switchMask) 
	{ 
		switchMask[initialId][startId] = currentChain; 
		wasHere[startId] = 1; 

		const vector_road_t& link = links[startId]; 
		for (size_t i = 0; i < link.size(); i++) 
		{ 
			const size_t nextId = link[i].to; 
			const uint32_t isImp = link[i].isImp; 
			if (wasHere[nextId]) 
				continue; 

			uint64_t chain = currentChain; 
			if (isImp) 
				chain |= (1ULL << link[i].id); 

			Walk(links, isImportant, wasHere, initialId, nextId, chain, switchMask); 
		} 
	} 

	uint64_t GetIntersectCount(const uint64_t x, const uint64_t y) 
	{ 
		uint64_t ans = 0; 
		if (x == y) 
			return 100; 
		for (size_t i = 0; i < 63; i++) 
		{ 
			const uint64_t d = 1ULL << i; 
			if ((x & d) && (y & d)) 
				ans++; 
		} 
		return ans; 
	} 

public: 
	int minimize(vector_int_t roads, string8_t initState, string8_t isImportant) 
	{ 
		const size_t n = roads.size() + 1; 
		vector_2d_road_t links(n); 

		for (size_t i = 0; i + 1 < n; i++) 
		{ 
			const size_t a = i + 1; 
			const size_t b = roads[i]; 
			const size_t id = i; 
			const uint32_t isImp = isImportant[i] == '1' ? 1 : 0; 
			links[a].push_back(road_t(b, id, isImp)); 
			links[b].push_back(road_t(a, id, isImp)); 
		} 

		uint64_t requiredMask = 0; 
		for (size_t i = 0; i + 1 < n; i++) 
		{ 
			if (isImportant[i] == '1' && initState[i] == '0') 
			{ 
				requiredMask |= (1ULL << i); 
			} 
		} 

		vector_2d_uint64_t switchMask(n, vector_uint64_t(n)); 
		for (size_t i = 0; i < n; i++) 
		{ 
			vector_int_t wasHere(n); 
			Walk(links, isImportant, wasHere, i, i, 0ULL, switchMask); 
		} 

		set_uint64_t options; 
		for (size_t i = 0; i < n; i++) 
		{ 
			for (size_t j = 0; j < n; j++) 
			{ 
				options.insert(switchMask[i][j]); 
			} 
		} 
		options.erase(0); 

		uint32_t ans = 0; 
		uint64_t currentMask = requiredMask; 
		while (currentMask) 
		{ 
			for (size_t i = 0; i < n; i++) 
			{ 
				if (currentMask & (1ULL << i)) 
				{ 
					uint64_t bestMatch = 0; 
					uint64_t bestMask = 0; 
					for (set_uint64_t::const_iterator pi = options.begin(); pi != options.end(); ++pi) 
					{ 
						const uint64_t nextMask = *pi; 
						if (currentMask & nextMask) 
						{ 
							const uint64_t cnt = GetIntersectCount(currentMask, nextMask); 
							if (cnt > bestMatch) 
							{ 
								bestMatch = cnt; 
								bestMask = nextMask; 
							} 
						} 
					} 

					currentMask ^= bestMask; 
					ans += 1; 
				} 
			} 
		} 

		return ans; 
	} 
};




using namespace std; 
#define pb push_back 
#define INF 1000000000 
#define L(s) (int)((s).size()) 
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++) 
#define rep(i,n) FOR(i,1,(n)) 
#define rept(i,n) FOR(i,0,(n)-1) 
#define C(a) memset((a),0,sizeof(a)) 
#define ll long long 
#define all(c) (c).begin(), (c).end() 
#define SORT(c) sort(all(c)) 
#define VI vector<int> 
#define ppb pop_back 
#define mp make_pair 
#define pii pair<int,int> 
#define x first 
#define y second 

vector<pii> sm[51]; 
VI mem[51]; 
int n; 

void rec(int v, int pr) { 
	if (L(mem[v])) return; 
	if (L(sm[v]) == 1 && pr != -1) { 
		mem[v].resize(n + 1); 
		rept(i, L(mem[v])) mem[v][i] = i; 
		return; 
	} 
	VI cur(n + 1, 0); 
	rept(i, L(cur)) cur[i] = i; 
	rept(i, L(sm[v])) { 
		int w = sm[v][i].x; 
		if (w == pr) continue; 
		rec(w, v); 
		VI t = mem[w]; 
		VI nt(L(t), INF); 
		rept(j, L(t)) { 
			FOR(add, -L(t), L(t)) { 
				if (j + add < 0 || j + add >= L(t)) continue; 
				if (sm[v][i].y != -1 && (j + add) % 2 != sm[v][i].y % 2) continue; 
				nt[j + add] = min(nt[j + add], t[j] + (add > 0 ? add : 0)); 
			} 
		} 
		t = nt; 
		nt = VI(L(t), INF); 
		rept(j, L(t)) { 
			FOR(add, -L(t), L(t)) { 
				if (j + add < 0 || j + add >= L(t)) continue; 
				nt[j + add] = min(nt[j + add], t[j] + (add > 0 ? add : 0)); 
			} 
		} 
		VI ncur(L(cur), INF); 
		rept(now, L(nt)) { 
			rept(old, L(cur)) { 
				if (now + old - 2 * min(now, old) < L(ncur)) { 
					ncur[now + old - 2 * min(now, old)] = min(ncur[now + old - 2 * min(now, old)], cur[old] + nt[now] - min(old, now)); 
				} 
			} 
		} 
		cur = ncur; 
	} 
	mem[v] = cur; 
} 

class TurnOnLampsKADR
{ 
public: 
	TurnOnLampsKADR
		()
	{
		for (size_t i = 0; i < 51; i++)
		{
			sm[i].clear();
			mem[i].clear();
		}

		n = 0;
	}
	int minimize( vector <int> roads, string initState, string isImportant ) 
	{ 
		rept(i, 51) sm[i].clear(); 
		n = L(roads) + 1; 
		rept(i, L(roads)) { 
			int a = roads[i]; 
			int b = i + 1; 
			if (isImportant[i] == '1') { 
				int t = 0; 
				if (initState[i] == '1') t = 0; else 
					t = 1; 
				sm[a].pb(mp(b, t)); 
				sm[b].pb(mp(a, t)); 
			} else { 
				sm[a].pb(mp(b, -1)); 
				sm[b].pb(mp(a, -1)); 
			} 
		} 
		rept(i, 51) mem[i].clear(); 
		int ans = INF; 
		rec(0, -1); 
		rept(i, L(mem[0])) { 
			ans = min(ans, mem[0][i]); 
		} 
		return ans; 
	} 
}; 


#include <iostream>
#include <iomanip>
#include <ctime>

template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}
template<typename T> inline void UpdateMax(T& a, const T b) {a = Max(a, b);}

template<typename T> inline std::ostream& operator<<(std::ostream& ost, const std::vector<T>& data)
{
	for (size_t i = 0; i < data.size(); i++) { if (i != 0) { ost << ' '; } ost << data[i]; }
	return ost;
}

struct stats_t
{
	stats_t()
	{
		m_timeStart = clock();
		testsPassed = 0;
		maxMovesCount = 0;
	}

	void Print()
	{
		const clock_t timeStop(clock());
		const unsigned long long durationMs = (((unsigned long long)1000 * (timeStop - m_timeStart) + CLOCKS_PER_SEC - 1) / CLOCKS_PER_SEC);

		std::cout << "Time elapsed : " << setw(10) << durationMs / 1000 << " s " << setw(3) << durationMs % 1000 << " ms"
			<< ", tests passed: " << std::setw(10) << testsPassed << ", max moves: " << std::setw(4) << maxMovesCount << std::endl;
	}

	clock_t m_timeStart;
	uint64_t testsPassed;
	int maxMovesCount;
};

stats_t g_stats;

void Test()
{
	clock_t lastPrintTime(clock());

	const size_t TestCount = 3000;
	const size_t MaxLen = 50;

	int errorsCount = 0;

	for (size_t t = 0; t < TestCount; t++)
	{
		const size_t len = rand() % (MaxLen - 1) + 2;
		vector_int_t roads(len - 1);
		for (size_t i = 0; i < roads.size(); i++)
		{
			roads[i] = rand() % (i + 1);
		}

		string8_t initialState(len - 1, '0');
		string8_t isImportant(len - 1, '0');

		for (size_t i = 0; i + 1 < len; i++)
		{
			initialState[i] = rand() % 2 + '0';
			isImportant[i] = rand() % 2 + '0';
		}

		if (rand() % 2 == 1)
			string8_t(isImportant.size(), '1').swap(isImportant);

		TurnOnLampsDmitriyH mySolution;
		TurnOnLampsKADR othersSolution1;

		const int myAns = mySolution.minimize(roads, initialState, isImportant);
		const int refAns = othersSolution1.minimize(roads, initialState, isImportant);

		g_stats.testsPassed += 1;
		UpdateMax(g_stats.maxMovesCount, myAns);

		clock_t currentTime(clock());
		const unsigned long long msFromLastPrint = (((unsigned long long)1000 * (currentTime - lastPrintTime) + CLOCKS_PER_SEC - 1) / CLOCKS_PER_SEC);
		if (msFromLastPrint > 1000)
		{
			g_stats.Print();
			lastPrintTime = currentTime;
		}

		if (myAns != refAns)
		{
			errorsCount += 1;
			std::cout << "Failed test case (id=" << t << ")" << std::endl;
			std::cout << "Expected ans = " << refAns << ", actual ans = " << myAns << std::endl;
			std::cout << len << std::endl;
			std::cout << roads << std::endl;
			std::cout << initialState << std::endl;
			std::cout << isImportant << std::endl;
			std::cout << "errorsCount = " << errorsCount << std::endl;
			std::cout << std::endl;
		}
	}

	g_stats.Print();	
	std::cout << "errorsCount = " << errorsCount << std::endl;	
}

int main()
{
	srand(0);
	Test();
	return 0;
}