并查集-讲课内容补全(未完

施工中......

先在这里给出我的并查集模板

以下为比较常用的

路径压缩

复制代码
int f[MAXN],n,m;
void clean() {
    for(int i=1; i<=n; i++) f[i]=i;
}
int find(int x) {
    if(x!=f[x]) f[x]=find(f[x]);
    return f[x];
}
void add(int x,int y) {
    int fx=find(x),fy=find(y);
    if(fx!=fy) f[fx]=fy;
}
复制代码

带权

复制代码
int find(int x) {
    if(x==f[x]) return x;
    else {
        int t=f[x];
        f[x]=find(f[x]);
        d[x]+=d[t];
        return f[x];
    }
}
void add(int x,int y,int v) {
    int fx=find(x),fy=find(y);
    if(fx!=fy) {
        f[fx]=fy;
        d[fx]=-d[x]+d[y]+v;
    }
}
复制代码

课后题目

A 宝可梦对决

HZNUOJ--宝可梦决战

思路:套用带权并查集 把权值%3  最后判断克制关系

实现代码(写的比较早 仅供参考)

复制代码
#include<iostream>
#include<stdio.h>
using namespace std;
int f[100000],d[100000];
int find(int x){
    if(x!=f[x])
    {
        int t=f[x];
        f[x]=find(f[x]);
        d[x]=(d[x]+d[t])%3;
    }
    
    return f[x];
}
void add(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx!=fy){
        f[fx]=fy;
        d[fx]=(d[y]-d[x]+1)%3;
    }
}
int main(){
    int n,t,i,x,y;
    scanf("%d %d",&n,&t);
    for(i=1;i<=n;i++)
    f[i]=i;
    while(t--){ 
        scanf("%d %d",&x,&y);
        add(x,y);
    }
    scanf("%d %d",&x,&y);
     find(x);find(y);
    //for(i=1;i<=n;i++)
    //cout<<d[i]<<endl;

   
    if(d[x]-d[y]==1||d[x]-d[y]==-2)
    cout<<"wait for me, my dear!"<<endl;
    else if(d[x]==d[y])
    cout<<"can I win the game?"<<endl;    
    else
        cout<<"change! change! change!"<<endl;    
    
}
View Code
复制代码

B 合根植物

思路:用并查集合起来,然后算根的个数就行了

复制代码
#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  2e6+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int f[MAXN],n,m;
void clean() {
    for(int i=1; i<=(n*m); i++) f[i]=i;
}
int find(int x) {
    if(x!=f[x]) f[x]=find(f[x]);
    return f[x];
}
void add(int x,int y) {
    int fx=find(x),fy=find(y);
    if(fx!=fy) f[fx]=fy;
}
void solve(){
    cin>>n>>m;
    clean();
    int q;cin>>q;
    while(q--){
        int u,v;cin>>u>>v;
        add(u,v);
    }
    int ans=0;
    for(int i=1;i<=n*m;i++){
        if(find(i)==i) ans++;
    }
    cout<<ans;
}
signed main(){
    solve();
}
View Code
复制代码

C 修复公路

建议学完最小生成树再来

思路:每次选最快的合并,合并到不能合并,然后输出最后一个合并的时间

复制代码
#include<bits/stdc++.h>
#define close std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const ll MAXN =  3e5+7;
const ll mod = 1e9+7;
const ll inf = 0x3f3f3f3f;
int f[MAXN],n,m;
struct node{
    int u,v,w;
}N[MAXN];
bool bj(node a,node b){
    return a.w<b.w;
}
void clean() {
    for(int i=1; i<=n; i++) f[i]=i;
}
int find(int x) {
    if(x!=f[x]) f[x]=find(f[x]);
    return f[x];
}
void add(int x,int y) {
    int fx=find(x),fy=find(y);
    if(fx!=fy) f[fx]=fy;
}
void solve(){
    cin>>n>>m;
    clean();
    for(int i=1;i<=m;i++){
        cin>>N[i].u>>N[i].v>>N[i].w;
    }
    sort(N+1,N+1+m,bj);
    int ans=0,cnt=0;
    for(int i=1;i<=m;i++){
        int u=N[i].u,v=N[i].v,w=N[i].w;
        if(find(u)!=find(v)){
            add(u,v);
            ans=max(ans,w);
        }
    }
    for(int i=1;i<=n;i++){
        if(find(i)==i) cnt++;
    }
    if(cnt>1) cout<<"-1";
    else cout<<ans;
}
signed main(){
    solve();
}
View Code
复制代码

 

posted @   xishuiw  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示