(图论)信息传递
\(有人得知自已的消息等价于找到最小环\)
\(有两种做法:\)
- \((1)栈:每过一个点将其放入栈中,因为存在环,必然会有走到某个点但是\\其已经在栈中的情况,这个时候进行pop操作,直到弹出该点,总共弹出的点数\\就是环的长度\)
- \((2)并查集:维护每个点到根节点的距离,如果发现有两个点属于一个集合\\那么他们之间再连一条边就构成了环\)
栈
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 2e5 + 7, M = N;
int n;
int p[N], stk[N];
bool st[N], in_stk[N];
int main() {
IO;
int n;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> p[i];
int ans = n;
for (int i = 1; i <= n; ++i) {
if (!st[i]) {
int tt = 0;
int j = i;
while (!st[j]) {
stk[++tt] = j;
st[j] = true;
in_stk[j] = true;
j = p[j];
}
if (in_stk[j]) {
int cnt = 1;
while (stk[tt] != j) {
in_stk[stk[tt--]] = false;
cnt++;
}
ans = min(ans, cnt);
}
while (tt) in_stk[stk[tt--]] = false;
}
}
cout << ans << '\n';
return 0;
}
并查集
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 2e5 + 7, M = N;
int p[N], dist[N];
int find(int u) {
if (u == p[u]) return u;
int y = p[u];
p[u] = find(y);
dist[u] += dist[y];
return p[u];
}
int main() {
IO;
int n;
cin >> n;
int ans = n;
for (int i = 1; i <= n; ++i) p[i] = i;
for (int i = 1; i <= n; ++i) {
int j;
cin >> j;
int x = find(i), y = find(j);
if (x != y) {
p[x] = y;
dist[i] = dist[j] + 1;
} else ans = min(ans, dist[i] + dist[j] + 1);
}
cout << ans << '\n';
return 0;
}