Submission #544497

#TimeUsernameProblemLanguageResultExecution timeMemory
544497model_codeJail (JOI22_jail)C++17
100 / 100
1710 ms446332 KiB
#include <bits/stdc++.h>
using namespace std;

// Input & Graph
int N, A[200009], B[200009];
int M, S[200009], T[200009];
int SVal[200009], TVal[200009];
int Sidx[200009][20];
int Tidx[200009][20];
vector<int> G[200009];
vector<int> H[9000009];

// Others
int NumVertices;
int parent[200009][20], dist[200009];
int indeg[9000009];
vector<int> tmp, Path;

void AllInit(int N, int M, int Verts) {
	for (int i = 0; i < N; i++) G[i].clear();
	for (int i = 0; i < Verts; i++) H[i].clear();
	NumVertices = 0;
}

void dfs_init(int pos, int par, int dep) {
	dist[pos] = dep;
	for (int to : G[pos]) {
		if (to == par) continue;
		parent[to][0] = pos;
		dfs_init(to, pos, dep + 1);
	}
}

int prevs(int pos, int x) {
	for (int i = 19; i >= 0; i--) {
		if (x >= (1 << i)) { pos = parent[pos][i]; x -= (1 << i); }
	}
	return pos;
}

int GetLCA(int u, int v) {
	if (dist[u] > dist[v]) swap(u, v);
	v = prevs(v, dist[v] - dist[u]);
	if (u == v) return u;
	for (int i = 19; i >= 0; i--) {
		if (parent[u][i] == parent[v][i]) continue;
		u = parent[u][i];
		v = parent[v][i];
	}
	return parent[u][0];
}

bool TopologicalSort() {
	for (int i = 0; i < NumVertices; i++) indeg[i] = 0;
	for (int i = 0; i < NumVertices; i++) {
		for (int j : H[i]) indeg[j] += 1;
	}
	
	queue<int> Q;
	for (int i = 0; i < NumVertices; i++) {
		if (indeg[i] == 0) Q.push(i);
	}
	while (!Q.empty()) {
		int pos = Q.front(); Q.pop();
		for (int to : H[pos]) {
			indeg[to] -= 1;
			if (indeg[to] == 0) Q.push(to);
		}
	}
	
	for (int i = 0; i < NumVertices; i++) {
		if (indeg[i] != 0) return false;
	}
	return true;
}

void AddS(int pos, int x, int base) {
	for (int i = 19; i >= 0; i--) {
		if (x < (1 << i)) continue;
		H[Sidx[pos][i]].push_back(base);
		x -= (1 << i);
		pos = parent[pos][i];
	}
}

void AddT(int pos, int x, int base) {
	for (int i = 19; i >= 0; i--) {
		if (x < (1 << i)) continue;
		H[base].push_back(Tidx[pos][i]);
		x -= (1 << i);
		pos = parent[pos][i];
	}
}

bool GetAnswer(int NN, vector<int> AA, vector<int> BB, int MM, vector<int> SS, vector<int> TT) {
	AllInit(N, M, NumVertices);
	N = NN;
	for (int i = 0; i < N - 1; i++) A[i] = AA[i] - 1;
	for (int i = 0; i < N - 1; i++) B[i] = BB[i] - 1;
	M = MM;
	for (int i = 0; i < M; i++) S[i] = SS[i] - 1;
	for (int i = 0; i < M; i++) T[i] = TT[i] - 1;
	
	// Step #1. Obvious Case
	for (int i = 0; i < N; i++) SVal[i] = -1;
	for (int i = 0; i < N; i++) TVal[i] = -1;
	for (int i = 0; i < M; i++) {
		if (SVal[S[i]] != -1) return false;
		else SVal[S[i]] = i;
		if (TVal[T[i]] != -1) return false;
		else TVal[T[i]] = i;
	}
	
	// Step #2. Make Graph
	for (int i = 0; i < N - 1; i++) {
		G[A[i]].push_back(B[i]);
		G[B[i]].push_back(A[i]);
	}
	
	// Step #3. Get LCA
	dfs_init(0, -1, 0);
	parent[0][0] = -1;
	for (int i = 0; i < 19; i++) {
		for (int j = 0; j < N; j++) {
			if (parent[j][i] == -1) parent[j][i + 1] = -1;
			else parent[j][i + 1] = parent[parent[j][i]][i];
		}
	}
	
	// Step #4. Init Sparse Table
	NumVertices = M;
	for (int i = 0; i < 20; i++) {
		for (int j = 0; j < N; j++) { NumVertices += 1; Sidx[j][i] = NumVertices; }
	}
	for (int i = 0; i < 20; i++) {
		for (int j = 0; j < N; j++) { NumVertices += 1; Tidx[j][i] = NumVertices; }
	}
	for (int i = 0; i < 19; i++) {
		for (int j = 0; j < N; j++) {
			int idx1 = Sidx[j][i + 1];
			int idx2 = Tidx[j][i + 1];
			int pars = parent[j][i];
			H[Sidx[j][i]].push_back(idx1);
			H[idx2].push_back(Tidx[j][i]);
			if (pars != -1) {
				H[Sidx[pars][i]].push_back(idx1);
				H[idx2].push_back(Tidx[pars][i]);
			}
		}
	}
	for (int i = 0; i < N; i++) {
		int idx1 = Sidx[i][0];
		int idx2 = Tidx[i][0];
		if (SVal[i] != -1) H[SVal[i]].push_back(idx1);
		if (TVal[i] != -1) H[idx2].push_back(TVal[i]);
	}
	
	// Step #5. Add Edges
	for (int i = 0; i < M; i++) {
		int LCA = GetLCA(S[i], T[i]);
		int LengthS = dist[S[i]] - dist[LCA];
		int LengthT = dist[T[i]] - dist[LCA];
		if (LengthS >= 2) {
			AddS(parent[S[i]][0], LengthS - 1, i);
			AddT(parent[S[i]][0], LengthS - 1, i);
		}
		if (LengthT >= 2) {
			AddS(parent[T[i]][0], LengthT - 1, i);
			AddT(parent[T[i]][0], LengthT - 1, i);
		}
		vector<int> Cand = {S[i], T[i], LCA};
		for (int j : Cand) {
			if (SVal[j] != i && SVal[j] != -1) H[SVal[j]].push_back(i);
			if (TVal[j] != i && TVal[j] != -1) H[i].push_back(TVal[j]);
		}
	}
	
	// Step #6. Topological Sort
	bool ret = TopologicalSort();
	return ret;
}

int main() {
	int Q;
	cin >> Q;
	for (int testcase = 1; testcase <= Q; testcase++) {
		// Input
		int NN, MM;
		cin >> NN;
		vector<int> AA(NN - 1, 0), BB(NN - 1, 0);
		for (int i = 0; i < NN - 1; i++) cin >> AA[i] >> BB[i];
		cin >> MM;
		vector<int> SS(MM, 0), TT(MM, 0);
		for (int i = 0; i < MM; i++) cin >> SS[i] >> TT[i];
		
		// Output
		bool FinalAns = GetAnswer(NN, AA, BB, MM, SS, TT);
		if (FinalAns == true) cout << "Yes" << endl;
		if (FinalAns == false) cout << "No" << endl;
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...