• HDU 2473 JunkMail Filter


    原来是这样啊、、、、、、、、、、、、、、、、、、!

    题意:给你一些相连的两点(带传递,显然是集合),并会对某些点进行删除操作,最终问你集合的数目

    显然是并查集,可是并查集,怎么去删除一个点呢??我想想想……晕了!不知道怎么删除。。最后……

    思想:删除操作就是用其他(用不到的)的点代替该点,JUST AND ONLY SO!!原集合中的该点JUST

    作为其它某些点的桥梁,通向根节点的桥梁,也就是ancestor[x]不变!若再删除,再用其它点代替,那么

    曾经的替代品也成了桥梁!!

    代码:

    View Code
    #include <stdio.h>
    #include <string.h>

    #define N 100002
    #define M 1000002

    //-----Union_Find_Set------------------
    int ancestor[N+M];
    int replace[N],ind;
    void Sinit(int n)
    {
    int i;
    for(i=0;i<n;i++)
    {
    ancestor[i]=i;
    replace[i]=i;
    }
    ind=n;
    }
    int Sfind(int x)
    {
    if(x!=ancestor[x])
    ancestor[x]=Sfind(ancestor[x]);
    return ancestor[x];
    }
    void Sunion(int x,int y)
    {
    int ancex=Sfind(x),ancey=Sfind(y);
    ancestor[ancex]=ancey;
    }
    void Sdelete(int x)
    {
    replace[x]=ind;
    ancestor[ind]=ind;
    ++ind;
    }
    //--------------------------------------------

    bool flag[N+M];

    int main()
    {
    int n,m;
    int i,x,y,ans,ance,cas=0;
    char c[2];

    // freopen("input.txt","r",stdin);
    while(scanf("%d %d",&n,&m) && n)
    {
    Sinit(n);
    for(i=0;i<m;i++)
    {
    scanf("%s",c);
    if(c[0]=='M')
    {
    scanf("%d %d",&x,&y);
    Sunion(replace[x],replace[y]);
    }
    else
    {
    scanf("%d",&x);
    Sdelete(x);
    }
    }

    memset(flag,false,sizeof(flag)); ans=0;
    for(i=0;i<n;i++)
    {
    ance=Sfind(replace[i]);
    if(!flag[ance])
    {
    ++ans;
    flag[ance]=true;
    }
    }

    printf("Case #%d: %d\n",++cas,ans);
    }

    return 0;
    }

    额,这题不错,让我知道了并查集的另一个操作,哈哈,有水平!!

  • 相关阅读:
    shell的执行顺序问题
    七层负载均衡——HAProxy
    不要自以为是码农
    SSL协议运行机制
    Linux启动流程
    MIM协议与Base64编码
    Adele的生活
    你值得拥有:25个Linux性能监控工具
    [Zabbix] 如何实现邮件报警通知以及免费短信报警通知
    php.ini中date.timezone设置分析
  • 原文地址:https://www.cnblogs.com/fornever/p/2240751.html
Copyright © 2020-2023  润新知