【BZOJ1589】[Usaco2008 Dec]Trick or Treat on the Farm 采集糖果【SCC】【基环外向树】【DP】【记忆化搜索】

http://www.lydsy.com/JudgeOnline/problem.php?id=1589

首先这是一个基环外向树,先tarjan缩点变成DAG,然后跑dp就行了。


记忆化搜索写成了

if(dp[x]) return x;

一定是没睡好...


/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 100005;

int n, dp[maxn], size[maxn], belong[maxn], next[maxn], to[maxn], dfn[maxn], low[maxn], clo, tot;
bool ins[maxn];

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

int sta[maxn], top;

inline void tarjan(int x) {
	dfn[x] = low[x] = ++clo;
	ins[sta[++top] = x] = 1;
	if(!dfn[next[x]]) tarjan(next[x]), low[x] = min(low[x], low[next[x]]);
	else if(ins[next[x]]) low[x] = min(low[x], dfn[next[x]]);
	if(low[x] == dfn[x]) {
		tot++;
		while(1) {
			int u = sta[top--];
			belong[u] = tot;
			size[tot]++;
			ins[u] = 0;
			if(u == x) break;
		}
	}
}

inline int dfs(int x) {
	if(dp[x]) return dp[x];
	dp[x] = size[x];
	if(to[x]) dp[x] += dfs(to[x]);
	return dp[x];
}

int main() {
	n = iread();
	for(int i = 1; i <= n; i++) next[i] = iread();
	for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= n; i++) if(belong[i] != belong[next[i]]) to[belong[i]] = belong[next[i]];
	for(int i = 1; i <= n; i++) printf("%d\n", dfs(belong[i]));
	return 0;
}


你可能感兴趣的:(【BZOJ1589】[Usaco2008 Dec]Trick or Treat on the Farm 采集糖果【SCC】【基环外向树】【DP】【记忆化搜索】)