b_aw_信息传递 & 银河英雄传说(并查集暴力求环 / 记忆化 | 带权并查集)

一、信息传递

有 n 个同学(编号为 1 到 n)正在玩一个信息传递的游戏。
在游戏里每人都有一个固定的信息传递对象,其中,编号为 i 的同学的信息传递对象是编号为 Ti 的同学。 
当有人从别人口中得知自己的生日时,游戏结束。
请问该游戏一共可以进行几轮?

输入样例:
5
2 4 2 3 1
输出样例:
3

方法一:暴力求环

  • 第i个人会把生日告诉a[i],如果你要求环的话,则i的父亲应该定义为a[i],即i指向a[i];为什么?因为如果有环的话,则下一次找的时候一定会有 a[i] 指向 i(i->a[i]->......->i),即当 find(a[i])=i 成立时

注:此解法不能用路劲压缩

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n, sz, fa[N], ans=N;
int find(int u) {
    sz++;
    return fa[u]==u ? u : find(fa[u]);
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n; for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=n; i++) {
        int x; cin>>x, sz=0;
        int fx=find(x);
        if (fx==i) {
            ans=min(ans, sz);
        } else {
            fa[i]=x;
        }
    }
    cout<<ans;
    return 0;
}

复杂度分析

  • Time\(O(n^2)\),应该是数据比较水
  • Space\(O(n)\)

方法二:记忆化优化


复杂度分析

  • Time\(O()\)
  • Space\(O()\)

二、银河英雄传说

有T条指令,每条指令格式为以下两种之一:
M i j,表示让第i号战舰所在列的全部战舰保持原有顺序,接在第j号战舰所在列的尾部。
C i j,表示询问第i号战舰与第j号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰
输入 T、op,i,j
数据范围
N≤30000,T≤500000

输入样例:
4
M 2 3
C 1 2
M 2 4
C 4 2
输出样例:
-1
1

方法一:并查集

假设 d[i]表示结点 i 和根节点 root 之间的战舰数量,那么 x、y 之间的战舰数量则为 |d[x]-d[y]|

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int fa[N], sz[N], d[N];
int find(int u) {
    if (fa[u]==u) return u;
    int root=find(fa[u]); //整棵树的根
    d[u]+=d[fa[u]];       //因为路径压缩之后u已经指向根了,所以在更新之前趁早维护d[u]
    return fa[u]=root;
}
void merge(int u, int v) {
    int fu=find(u), fv=find(v);
    if (fu!=fv)  {
        fa[fu]=fv;
        d[fu]=sz[fv];
        sz[fv]+=sz[fu];
    }
}
int query(int u, int v) {
    int fu=find(u), fv=find(v);
    if (fu!=fv) return -1;
    return abs(d[u]-d[v])-1;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t; cin>>t; for (int i=1; i<N; i++) fa[i]=i, sz[i]=1;
    while (t--) {
        char op; 
        int a,b; cin>>op>>a>>b;
        if (op=='M') {
            merge(a,b);
        } else {
            cout<<query(a,b)<<'\n';
        }
    }
    return 0;
}

类似:https://www.luogu.com.cn/problem/solution/P2294

原文地址:https://www.cnblogs.com/wdt1/p/13641621.html