Solution - P5676 [GZOI2017] 小z玩游戏

不是???为什么栈需要清空???

思路

很简单的一个思路,把转移干成边跑 tarjan 就行了。显然 \(1\) 能到达全图。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
#define M 20000007
using namespace std;

int to[M], nxt[M], head[N], gsiz;
#define mkarc(u,v) (++gsiz,to[gsiz]=v,nxt[gsiz]=head[u],head[u]=gsiz)
int dfn[N], low[N], dfcnt;
int belong[N], n2, sta[N], top;
int s[N], t[N];
int n, m, ans;

inline void tarjan(rint u){
	dfn[u] = low[u] = ++dfcnt;
	sta[++top] = u;
	for(rint i = head[u]; i; i = nxt[i]){
		rint v = to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(!belong[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u]){
		++n2;
		while(sta[top+1] != u)
			belong[sta[top--]] = n2;
	}
	return;
}

int _main(){
	for(rint i = 1; i <= n; ++i)
		dfn[i] = low[i] = head[i] = belong[i] = sta[i] = 0;
	scanf("%d", &m), n = n2 = ans = gsiz = dfcnt = 0;
	for(rint i = 1; i <= m; ++i)
		scanf("%d", &s[i]), n = max(n, s[i]);
	for(rint i = 1; i <= m; ++i)
		scanf("%d", &t[i]), n = max(n, t[i]);
	for(rint i = 1; i <= m; ++i)
		mkarc(s[i], t[i]);
	for(rint i = 1; i <= n; ++i)
		for(rint j = 2; i*j <= n; ++j)
			mkarc(i, i*j);
	tarjan(1);
	for(rint i = 1; i <= m; ++i)
		if(belong[s[i]] == belong[t[i]] && belong[s[i]] != 0) ++ans;
	printf("%d\n", ans);
	return 0;
}

int ccf;
int main(){
	scanf("%d", &ccf);
	while(ccf--) _main();
	return 0;
}

posted @ 2025-05-14 16:35  Hootime  阅读(5)  评论(0)    收藏  举报