3/25《并查集》

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3/25《并查集》相关的知识,希望对你有一定的参考价值。

P1892 [BOI2003]团伙
数组记录敌人;且在每次合并前,先合并别人的敌人

#include <bits/stdc++.h>

using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e4+5;
int p[maxn],f[maxn],n,m;
int r_find(int r)

    if(f[r]==r)
        return r;
    f[r]=r_find(f[r]);
    return f[r];

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    
        char c;int a,b;
        cin>>c>>a>>b;
        if(c=='F')
        
            int fx=r_find(a),fy=r_find(b);
            f[fx]=fy;
        
        if(c=='E')
        
            if(p[a])
            
                int fx=r_find(p[a]),fy=r_find(b);
                f[fx]=fy;
            
            if(p[b])
            
                int fx=r_find(a),fy=r_find(p[b]);
                f[fx]=fy;
            
            p[a]=b,p[b]=a; //存储敌人
        
    
    int ans=0;
    for(int i=1;i<=n;i++)
    
        if(f[i]==i) ans++;
    
    cout<<ans<<endl;
    return 0;


P1955 [NOI2015] 程序自动分析
离散化处理+并查集。。。。思路是不难,但这离散化处理确实麻烦
1.进行排序,然后去重。
2.lowerbound进行下标的查找

#include <bits/stdc++.h>

using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int f[maxn],book[maxn*3],n,m;
struct node

    int x,y,z;
e[maxn];
bool cmp(node e1,node e2)

    return e1.z>e2.z;

int r_find(int r)

    if(f[r]==r)
        return r;
    f[r]=r_find(f[r]);
    return f[r];

signed main()

    int t;cin>>t;
    while(t--)
    
        int tol=0;cin>>n;
        memset(book,0,sizeof(book));
        for(int i=1;i<=n;i++)
            cin>>e[i].x>>e[i].y>>e[i].z;
            book[++tol]=e[i].x,book[++tol]=e[i].y;
        
        sort(book+1,book+tol+1);
        int cnt=unique(book+1,book+tol+1)-book-1;
        for(int i=1;i<=n;i++)
        
            e[i].x=lower_bound(book+1,book+cnt+1,e[i].x)-book;
            e[i].y=lower_bound(book+1,book+cnt+1,e[i].y)-book;
        
        for(int i=1;i<=cnt;i++) f[i]=i;
        int flag=1;
        sort(e+1,e+n+1,cmp);
        for(int i=1;i<=n;i++)
        
            int fx=r_find(e[i].x),fy=r_find(e[i].y);
            if(e[i].z==1)
                f[fx]=fy;
            else if(e[i].z==0)
            
                if(fx==fy)
                
                    cout<<"NO"<<endl;flag=0;break;
                
            
        
        if(flag)
            cout<<"YES"<<endl;
    

    return 0;

P1991 无线通讯网
主要是对于电话的处理。共p个灯塔,需要p-1条边,最后的(s-1)个边放电话。

#include <bits/stdc++.h>

using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int f[maxn],s,p,a[maxn],b[maxn],cnt;
struct node

    int x,y;double dis;
e[maxn];
bool cmp(node e1,node e2)

    return e1.dis<e2.dis;

int r_find(int r)

    if(f[r]==r)
        return r;
    f[r]=r_find(f[r]);
    return f[r];

double cal(int x1,int y1,int x2,int y2)

    return (double)sqrt((x1-x2)*(x1-x2)*1.0+(y1-y2)*(y1-y2)*1.0);

signed main()

    scanf("%d%d",&s,&p);
    for(int i=1;i<=p;i++)
        scanf("%d%d",&a[i],&b[i]);
    for(int i=1;i<p;i++)
        for(int j=i+1;j<=p;j++)
    
        e[++cnt].x=i,e[cnt].y=j,e[cnt].dis=cal(a[i],b[i],a[j],b[j]);
    
    sort(e+1,e+cnt+1,cmp);
    for(int i=1;i<=p;i++) f[i]=i;
    int ans=0;
    for(int i=1;i<=cnt;i++)
    
        int fx=r_find(e[i].x),fy=r_find(e[i].y);
        if(fx!=fy)
        
            f[fx]=fy;ans++;
            if(ans>=(p-1)-(s-1))
            
                ans=i;break;
            
        
    
    cout<<fixed<<setprecision(2)<<e[ans].dis<<endl;
    return 0;

背包

举例:10000个物品利用二进制优化,拆分成1,2,4,8,16,32,64,128……个,剩下的不满则10000去减。

int t=1;
while(x>=t)

    v[cnt]=a*t;
    c[cnt++]=b*t;
    x-=t;t<<=1;

if(x)

    v[cnt]=a*x;
    b[cnt++]=b*x;

P2170 选学霸
难点在于背包的处理。
记得学一下bitset优化的01背包!!!

#include <bits/stdc++.h>

using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
int f[maxn],n,m,k,sz[maxn],p[maxn],cnt,dp[maxn];
int r_find(int r)

    if(f[r]==r)
        return r;
    f[r]=r_find(f[r]);
    sz[r]=sz[f[r]];
    return f[r];

signed main()

    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;
    for(int i=1;i<=k;i++)
    
        int a,b;cin>>a>>b;
        int fx=r_find(a),fy=r_find(b);
        if(fx!=fy)
        
            f[fx]=fy;
            sz[fx]+=sz[fy];
            sz[fy]=sz[fx];
        
    
    for(int i=1;i<=n;i++)
    
        if(f[i]==i)
        
            p[++cnt]=sz[i];
        
    
    dp[0]=true;
    for(int i=1; i<=cnt; i++)
        for(int j=n; j>=p[i]; j--)
            if(!dp[j]&&dp[j-p[i]])
                dp[j]=true;
    int ans=inf,minn=inf;
    for(int i=0; i<=n; i++)
        if(dp[i]&&abs(i-m)<minn) minn=abs(i-m),ans=i;
    cout<<ans<<endl;
    return 0;


以上是关于3/25《并查集》的主要内容,如果未能解决你的问题,请参考以下文章

[qbzt寒假] 并查集

并查集团伙

BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)

P1525 关押罪犯(二分图/并查集)

并查集之团伙(codevs)

团伙(并查集经典)