zoukankan      html  css  js  c++  java
  • 【提高组】并查集

    (时隔多日回归刷题日常...果然还是刷题最快乐)

    P1111 修复公路

    按时间sort一遍,每次合并两个节点,显然如果原先不连通那么合并之后联通块数量--。然后如果n==1就输出当前时间return。

    #include<bits/stdc++.h>
    #define For(i,l,r) for(int i=l;i<=r;i++)
    using namespace std;
    const int M=2e5+5; 
    struct node{
        int x,y,t;
    }e[M];
    int fa[M],n,m;
    inline int cmp(const node x,const node y){return x.t<y.t;}
    inline int getfa(int x){return fa[x]==x?x:getfa(fa[x]);}
    inline int read(){
        int f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} 
        return f*sum;
    }
    int main(){
        n=read(),m=read();
        For(i,1,m) e[i].x=read(),e[i].y=read(),e[i].t=read();
        sort(e+1,e+m+1,cmp);
        For(i,1,n) fa[i]=i;
        For(i,1,m){ 
            int fx=getfa(e[i].x),fy=getfa(e[i].y);
            if(fx!=fy) fa[fx]=fy,n--;
            if(n==1) {printf("%d
    ",e[i].t);return 0;}
        }
        printf("-1
    ");
        return 0;
    } 
    View Code

    P2024 [NOI2001]食物链

    巨简单的思路果然一交就挂,20分,但不知道错在哪里。

    看了题解,学了带权并查集,一知半解吧,再去看几道题。

    f[x]意义不变,re[x]记录关系AKA权值,没搞懂怎么推出来的。

    我懂了,带权并查集真好。

    #include<bits/stdc++.h>
    #define For(i,l,r) for(int i=l;i<=r;i++)
    using namespace std;
    const int M=1e5+5;
    int f[M],re[M];
    int n,m,k,x,y,ans;
    int getfa(int a){
        int fa=f[a];
        if(a!=fa){
            f[a]=getfa(fa);
            re[a]=(re[a]+re[fa])%3;   
            return f[a];
        }
        else return fa;
    }
    int main(){
        cin>>n>>m;
        For(i,1,n) f[i]=i;
        while(m--){
            cin>>k>>x>>y;
            if(x>n||y>n||(k==2&&x==y)){ans++;continue;}
            if(k==1){
                int fx=getfa(x),fy=getfa(y);
                if(fx==fy&&re[x]!=re[y]){ans++;continue;}    
                else if(fx!=fy){f[fx]=fy;re[fx]=(re[y]-re[x]+3)%3;}
            }
            if(k==2){
                int fx=getfa(x),fy=getfa(y);
                if(fx==fy){
                    int rela=(re[x]-re[y]+3)%3;
                    if(rela!=1){ans++;continue;}  
                }
                else f[fx]=fy,re[fx]=(re[y]-re[x]+4)%3;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    P1197 [JSOI2008]星球大战

    一眼看过去完全没思路(也不是就是有的思路绝对T)。

    结果题解告诉我 逆向思维 #做道题学个思路/算法

    详细解释看代码,不是很难打,难在想,

    #include<bits/stdc++.h>
    #define ri register int
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=4e5+5;
    int n,m,k,head[M],tot,a[M],ans[M],f[M];
    bool bm[M];
    struct node{
        int from,to,nxt;
    }e[M];
    inline void add(int u,int v){
        e[++tot].from=u;
        e[tot].nxt=head[u];
        e[tot].to=v;
        head[u]=tot;
    }
    inline int getfa(int x){
        if(f[x]==x)return x;
        return f[x]=getfa(f[x]);
    }
    inline void hb(int u,int v){
        int fu=getfa(u),fv=getfa(v);
        if(fu!=fv) f[fv]=fu;
    }
    int main(){
        cin>>n>>m;
        For(i,0,n) f[i]=i;
        For(i,1,m){int x,y;cin>>x>>y;add(x,y),add(y,x);}
        cin>>k;
        For(i,1,k){cin>>a[i];bm[a[i]]=1;}//bm标记城市已被砸 
        int total=n-k;//初始化所有城市都单独存在 
        For(i,1,m<<1){//2*m条边 
            if(!bm[e[i].from]&&!bm[e[i].to]&&getfa(e[i].from)!=getfa(e[i].to)){total--;hb(e[i].from,e[i].to);}
        }//起点和终点都没被砸坏且两点不连通,连一条边,联通块-- 
        ans[k+1]=total;//最后一次破坏后的个数 
        Dfor(i,k,1){//倒着枚举 
            total++;bm[a[i]]=0;//修复一个点联通块++ 
            for(int j=head[a[i]];j;j=e[j].nxt){//枚举每一个子点 
                if(!bm[e[j].to]&&getfa(a[i])!=getfa(e[j].to)){total--;hb(a[i],e[j].to);}
            }//子点没被炸且两点不在同一个联通块,连一条边减一个联通块 
            ans[i]=total;//记录当前连通块数量 
        }
        For(i,1,k+1){cout<<ans[i]<<endl;}
        return 0;
    }
    View Code
  • 相关阅读:
    [导入]如何使用C#调用非托管DLL函数
    [导入]ASP.NET 2.0 Page的执行顺序
    [导入]C#实现捕获当前屏幕截图(转)
    初学者入门经典:Java环境配置大全
    [导入]使用母版页时内容页如何使用css和javascript(转)
    CruiseControl.NET配置总结
    使用SQL语句清空数据库所有表的数据
    运行时修改config文件
    [导入]Repater 控件的应用(学习)
    [导入]PictureBox 读取图片及绘画
  • 原文地址:https://www.cnblogs.com/jian-song/p/11720598.html
Copyright © 2011-2022 走看看