这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
|
2020-2021:teams:no_morning_training:shaco:知识点:数据结构:并查集 [2020/06/30 11:45] shaco |
2020-2021:teams:no_morning_training:shaco:知识点:数据结构:并查集 [2020/07/06 09:15] (当前版本) shaco |
||
|---|---|---|---|
| 行 3: | 行 3: | ||
| 并查集应用广泛,用于判断元素是否属于同一个集合以及合并集合。 | 并查集应用广泛,用于判断元素是否属于同一个集合以及合并集合。 | ||
| ==== 复杂度 ==== | ==== 复杂度 ==== | ||
| - | 最坏到 $O(n)$,单独使用路径压缩达到 $O(n+f(1+\log_{2+f/n}n))$,单独使用按秩合并可达到 $O(\log{n})$,两者同时使用可以达到 $O(\alpha (n))$,其中 $\alpha (n)$ 是阿克曼函数的反函数,可以认为非常小(这部分参照网上)。按秩合并即每次将小的集合合并到大的集合中去,可以减少修改次数。 | + | 最坏到 $O(n)$,单独使用路径压缩达到 $O(n+f(1+\log_{2+f/n}n))$,单独使用按秩合并可达到 $O(\log{n})$,两者同时使用可以达到 $O(\alpha (n))$,其中 $\alpha (n)$ 是阿克曼函数的反函数,可以认为非常小。按秩合并即每次将小的集合合并到大的集合中去,可以减少修改次数。 |
| ==== 概念 ==== | ==== 概念 ==== | ||
| 每个集合有一个代表元素,每一个元素通过一个数组记录其所属集合的代表元素。判断两个元素是否属于同一个集合时查询它们的代表元素是否相同,合并集合时将一个集合的代表元素更替为另一个集合的代表元素。 | 每个集合有一个代表元素,每一个元素通过一个数组记录其所属集合的代表元素。判断两个元素是否属于同一个集合时查询它们的代表元素是否相同,合并集合时将一个集合的代表元素更替为另一个集合的代表元素。 | ||
| 行 105: | 行 105: | ||
| <hidden code> | <hidden code> | ||
| <code cpp> | <code cpp> | ||
| + | #include<cstdio> | ||
| + | #include<algorithm> | ||
| + | using namespace std; | ||
| + | int t,n,intr,fa[2005][2],m[2005]; | ||
| + | int Find(int x) | ||
| + | { | ||
| + | if(fa[x][0]==x) return x; | ||
| + | int f=Find(fa[x][0]); | ||
| + | fa[x][1]=!(fa[x][1]^fa[fa[x][0]][1]); | ||
| + | return fa[x][0]=f; | ||
| + | } | ||
| + | int Merge(int x,int y) | ||
| + | { | ||
| + | int fx=Find(x),fy=Find(y); | ||
| + | if(fx==fy) | ||
| + | { | ||
| + | if(fa[x][1]==fa[y][1]) | ||
| + | return 0; | ||
| + | return 1; | ||
| + | } | ||
| + | if(m[fx]>m[fy]) swap(fx,fy),swap(x,y); | ||
| + | m[fy]+=m[fx]; | ||
| + | fa[fx][0]=fy; | ||
| + | fa[fx][1]=!(fa[x][1]^(!fa[y][1])); | ||
| + | return 1; | ||
| + | } | ||
| + | int main() | ||
| + | { | ||
| + | scanf("%d",&t); | ||
| + | for(int T=1;T<=t;T++) | ||
| + | { | ||
| + | scanf("%d%d",&n,&intr); | ||
| + | for(int i=1;i<=n;i++) | ||
| + | { | ||
| + | fa[i][0]=i; | ||
| + | m[i]=fa[i][1]=1; | ||
| + | } | ||
| + | int v=1; | ||
| + | for(int i=1,a,b;i<=intr;i++) | ||
| + | { | ||
| + | scanf("%d%d",&a,&b); | ||
| + | v&=Merge(a,b); | ||
| + | } | ||
| + | if(T>1) printf("\n\n"); | ||
| + | printf("Scenario #%d:\n",T); | ||
| + | if(v) printf("No suspicious bugs found!"); | ||
| + | else printf("Suspicious bugs found!"); | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | |||
| </code> | </code> | ||
| </hidden> | </hidden> | ||
| ==== poj 1182 食物链 ==== | ==== poj 1182 食物链 ==== | ||
| [[http://poj.org/problem?id=1182|poj1182]] | [[http://poj.org/problem?id=1182|poj1182]] | ||
| + | |||
| + | 题意:有三种动物,处在一个捕食循环上($1\to2\to3\to1$),给出若干组捕食或者同类关系,判断假话的数量。假话即是与之前的非假话矛盾的话或不符合数据范围条件的话(这条不是重点)。 | ||
| + | |||
| + | 这一题也是带权值,处理方式和上一题相似,关键在于处理好权值之间的计算关系。 | ||
| + | |||
| + | <hidden code> | ||
| + | <code cpp> | ||
| + | #include<cstdio> | ||
| + | #include<algorithm> | ||
| + | using namespace std; | ||
| + | int n,k,d,x,y,ans=0,fa[50005][2],m[50005]; | ||
| + | int Find(int x) | ||
| + | { | ||
| + | if(fa[x][0]==x) return x; | ||
| + | int f=Find(fa[x][0]); | ||
| + | fa[x][1]=(fa[x][1]+fa[fa[x][0]][1])%3; | ||
| + | return fa[x][0]=f; | ||
| + | } | ||
| + | int Merge(int d,int x,int y) | ||
| + | { | ||
| + | if(x>n||y>n||(d&&x==y)) return 1; | ||
| + | int fx=Find(x),fy=Find(y); | ||
| + | if(fx==fy) | ||
| + | { | ||
| + | if((fa[x][1]+d+3)%3==fa[y][1]) return 0; | ||
| + | return 1; | ||
| + | } | ||
| + | if(m[fx]>m[fy]) swap(fx,fy),swap(x,y),d=-d; | ||
| + | m[fy]+=m[fx]; | ||
| + | fa[fx][0]=fy; | ||
| + | fa[fx][1]=(fa[y][1]-d-fa[x][1]+3)%3; | ||
| + | return 0; | ||
| + | } | ||
| + | int main() | ||
| + | { | ||
| + | scanf("%d%d",&n,&k); | ||
| + | for(int i=1;i<=n;i++) | ||
| + | { | ||
| + | fa[i][0]=i; | ||
| + | fa[i][1]=0; | ||
| + | m[i]=1; | ||
| + | } | ||
| + | for(int i=1;i<=k;i++) | ||
| + | { | ||
| + | scanf("%d%d%d",&d,&x,&y); | ||
| + | ans+=Merge(d-1,x,y); | ||
| + | } | ||
| + | printf("%d",ans); | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | </hidden> | ||
| ===== 参考 ===== | ===== 参考 ===== | ||
| [[https://www.nowcoder.com/profile/2315431/note/detail/316067]] | [[https://www.nowcoder.com/profile/2315431/note/detail/316067]] | ||