第一看还以为是水题
随便打了一个bfs只有40分……
然后开始颓废
#include<bits/stdc++.h> #define N 100005 using namespace std; int nxt[N]; bool vis[N]; void bfs(int x) { memset(vis, 0, sizeof(vis)); queue<int>q; q.push(x); vis[x] = true; int cnt = 1; while (!q.empty()) { int now = q.front(); if (vis[nxt[now]] == true) { printf("%d ", cnt); return; } else { q.pop(); q.push(nxt[now]); cnt++; vis[nxt[now]] = true; } } } int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &nxt[i]); } for(int i=1;i<=n;i++) bfs(i); }
然后在水社区的时候
看到一个当时和我一起打这道题的网友@Frozencode (貌似是位大佬)提到这道题
一开始没怎么想写博客的
但是现在还是写吧
思路
之前是bfs,想用记忆化很难实现(我这个蒟蒻没打出来,大佬见笑了)
一开始想储存到一个点的需要的步骤储存下来
但是bfs会一直更新,不能那么草率地使用啊
然后看tag是DP?我不会DP
于是颓废的我点开了题解
题解一个是玄学模拟。我不会模拟
然后大神们很多写的Tarjan。为了试图看懂大佬的代码,我甚至想去学tarjan。但是我不会tarjan。
无奈之下,我还是回归开始的搜索,但是打dfs。
结果过了……
代码
献丑了
VS的码风
#include<bits/stdc++.h> #define N 100005 using namespace std; int n,x,to[N],rd[N],w[N],dep[N],mk[N]; char vis[N], ins[N]; int dfs(int x); int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d",&to[i]),++rd[to[i]]; for (int i = 1; i <= n; ++i) if (!rd[i]) w[i] = 1, dfs(i); for (int i = 1; i <= n; ++i) if (!vis[i]) dfs(i); for (int i = 1; i <= n; ++i) printf("%d ",w[i]); return 0; } int dfs(int x) { int t = to[x]; vis[x] = ins[x] = 1; if (!vis[t]) { dep[t] = dep[x] + 1; w[x] = dfs(t); w[x] += (mk[t] ? (mk[x] = (mk[x] != 2 ? 1 : 0), 0) : 1); } else if (ins[t]) w[x] = dep[x] - dep[t] + 1, mk[x] = 1, mk[t] = (x == t ? 0 : 2); else w[x] = w[t] + 1; ins[x] = 0; return w[x]; }
想睡觉了……因此不多解释了
现在23:11
思路也大多数是看题解的
我去找找……
找到了
这位大神的https://www.luogu.org/blog/backupnoob/solution-p2921
虽然压行可读性低,但是基本可以看懂
(说白了吧,我抄题解的……)
深深感觉到自己的弱小