QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#357810#6559. A Tree and Two Edgesec1117WA 2ms6824kbC++145.0kb2024-03-19 12:53:412024-03-19 12:53:42

Judging History

你现在查看的是最新测评结果

  • [2024-03-19 12:53:42]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:6824kb
  • [2024-03-19 12:53:41]
  • 提交

answer

#include <bits/stdc++.h>
#include <random>
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pi;
typedef vector<int> vi; 
typedef vector<pi> vpi;

#define mp make_pair
#define f first
#define s second
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rsz resize
#define bk back()
#define pb push_back

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define For(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

const int MOD = 1e9+7;
const ld PI = acos((ld)-1);
mt19937 rng; // or mt19937_64
template<class T> bool ckmin(T& a, const T& b) { 
	return b < a ? a = b, 1 : 0; }

void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
	cerr << h; if (sizeof...(t)) cerr << ", ";
	DBG(t...); }
#ifdef LOCAL // compile with -DLOCAL
#define dbg(...) cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif

/**
 * Description: Disjoint Set Union with path compression
 	* and union by size. Add edges and test connectivity. 
 	* Use for Kruskal's or Boruvka's minimum spanning tree.
 * Time: O(\alpha(N))
 * Source: CSAcademy, KACTL
 * Verification: USACO superbull
 */

struct DSU {
	vi e; void init(int n) { e = vi(n,-1); }
	int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); } 
	bool sameSet(int a, int b) { return get(a) == get(b); }
	int size(int x) { return -e[get(x)]; }
	bool unite(int x, int y) { // union by size
		x = get(x), y = get(y); if (x == y) return 0;
		if (e[x] > e[y]) swap(x,y);
		e[x] += e[y]; e[y] = x; return 1;
	}
};

/**template<class T> T kruskal(int n, vector<pair<T,pi>> ed) {
	sort(all(ed));
	T ans = 0; DSU D; D.init(n+1); // edges that unite are in MST
	trav(a,ed) if (D.unite(a.s.f,a.s.s)) ans += a.f; 
	return ans;
}*/

/**
 * Description: Calculates least common ancestor in tree 
 	* with root $R$ using binary jumping. 
 * Time: O(N\log N) build, O(\log N) query
 * Memory: O(N\log N)
 * Source: USACO Camp
 * Verification: Debug the Bugs
 */

template<int SZ> struct LCA {
	static const int BITS = 32-__builtin_clz(SZ);
	int N, R = 1, par[BITS][SZ], depth[SZ]; vi adj[SZ]; 
	/// INITIALIZE
	void ae(int u, int v) { adj[u].pb(v), adj[v].pb(u); }
	void dfs(int u, int prv){
		depth[u] = depth[par[0][u] = prv]+1;
		trav(v,adj[u]) if (v != prv) dfs(v,u); }
	void init(int _N) {
		N = _N; dfs(R,0);
		FOR(k,1,BITS) FOR(i,1,N+1) 
			par[k][i] = par[k-1][par[k-1][i]];
	}
	/// QUERY
	int getPar(int a, int b) {
		R0F(k,BITS) if (b&(1<<k)) a = par[k][a];
		return a; }
	int lca(int u, int v){
		if (depth[u] < depth[v]) swap(u,v);
		u = getPar(u,depth[u]-depth[v]);
		R0F(k,BITS) if (par[k][u] != par[k][v]) 
			u = par[k][u], v = par[k][v];
		return u == v ? u : par[0][u];
	}
	int dist(int u, int v) { // # edges on path
		return depth[u]+depth[v]-2*depth[lca(u,v)]; }
};


const int SZ = 1<<17;
DSU dsu;
LCA<SZ> lca;
vpi edg;

bool ins(int A, int B, int C) {
	int L = lca.lca(A,B);
	if(lca.lca(C,L)==L && (lca.lca(C,A)==C || lca.lca(C,B)==C)) {
		return true;
	}
	return false;
}

bool intersect(int A, int B, int C, int D) {
	int L = lca.lca(C,D);
	// dbg(A,B,C,D,L);
	// dbg("B",ins(A,B,C), ins(A,B,D), ins(A,B,L));
	if (ins(A,B,C) || ins(A,B,D) || ins(A,B,L)) {
		return true;
	}
	return false;
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0); 
	int n,q;cin>>n>>q;
	dsu.init(n+1);

	For(i,n+1) {
		int u,v;cin>>u>>v;
		
		if(!dsu.unite(u,v)) {
			dbg(u,v);
			edg.pb({u,v});
		} else {
			lca.ae(u,v);
		}
	}
	dbg("C");
	lca.init(n);
	dbg("D", edg.size());

	assert(edg.size() == 2);
	
	For(i,q) {
		int A,B;cin>>A>>B;
		int ans = 1;

		For(k,2) {
			int C = edg[k].f;
			int D = edg[k].s;
			if(!intersect(A,C,B,D) || !intersect(A,D,C,B)) {
				// 
				dbg(A,B,C,D);
				ans++;
			}
		}

		For(j,2) {
			For(k,2)For(l,2) {
				pi t1 = edg[0];
				pi t2 = edg[1];
				if(k) 
					swap(t1.f,t1.s);
				if(l) 
					swap(t2.f,t2.s);

				vpi vv = {t1,t2};
				if(j)
					swap(vv[0],vv[1]);
				bool bb = !intersect(A,vv[0].f, vv[0].s, vv[1].f) && !intersect(vv[0].s,vv[1].f,vv[1].s,B) && !intersect(A,vv[0].f,vv[1].s,B);
				if(bb){
					dbg("Big boy");
					ans++;
					goto done;
				}
			}
		}
		done:;
		// int C = edg[0].f, D = edg[0].s;
		// int E = edg[1].f, F = edg[1].s;

		// bool b1 = !intersect(A,C,D,E) && !intersect(D,E,F,B) && !intersect(A,C,F,B);
		// bool b1 = !intersect(A,C,D,F) && !intersect(D,F,E,B) && !intersect(A,C,E,B);
		// bool b1 = !intersect(A,D,C,E) && !intersect(C,E,F,B) && !intersect(A,D,F,B);
		// bool b1 = !intersect(A,D,C,F) && !intersect(C,F,E,B) && !intersect(A,D,E,B);

		cout << "ANS: " << ans << '\n';
	}
}


/* stuff you should look for
	* int overflow, array bounds
	* special cases (n=1?)
	* do smth instead of nothing and stay organized
	* WRITE STUFF DOWN
*/

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 2ms
memory: 6824kb

input:

4 6
1 2
1 3
1 4
2 3
2 4
1 2
1 3
1 4
2 3
2 4
3 4

output:

ANS: 3
ANS: 3
ANS: 3
ANS: 3
ANS: 3
ANS: 4

result:

wrong answer 1st lines differ - expected: '3', found: 'ANS: 3'