(图论)信息传递

题目链接

\(有人得知自已的消息等价于找到最小环\)

\(有两种做法:\)

  • \((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;
}


posted @ 2021-02-28 15:36  phr2000  阅读(90)  评论(0编辑  收藏  举报