题解 P2921 【[USACO08DEC]在农场万圣节Trick or Treat on the Farm】

pantw

2018-01-16 20:44:24

Solution

做法类似于NOIP2015 D1T2 message。 拓扑排序删链 → 对环上的点计算答案 → dfs计算其他点的答案。 环上的点答案都一样,可以一遍dfs跑出来; 其他点的答案在dfs返回的时候+1即可。 实现细节详见代码。 ```cpp #include <cstdio> #define maxn 100010 int next[maxn], in[maxn], ans[maxn]; bool vis[maxn]; void del(int cur) { vis[cur] = true; in[next[cur]]--; if(!in[next[cur]]) del(next[cur]); } int calccircle(int cur, int depth) { ans[cur] = depth; if(ans[next[cur]]) return depth; else return ans[cur] = calccircle(next[cur], depth + 1); } int calc(int cur) { if(ans[cur]) return ans[cur]; else return ans[cur] = calc(next[cur]) + 1; } int main() { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", next + i), in[next[i]]++; for(int i = 1; i <= n; i++) if(!in[i] && !vis[i]) del(i); for(int i = 1; i <= n; i++) if(in[i] && !ans[i]) calccircle(i, 1); for(int i = 1; i <= n; i++) if(!in[i] && !ans[i]) calc(i); for(int i = 1; i <= n; i++) printf("%d\n", ans[i]); } ```