zoukankan      html  css  js  c++  java
  • Hdu 2473(并查集删除操作) Junk-Mail Filter

      有木有非常吊  

    加强

    加强版   啊  ,看了都不敢做了   。后来先做了食物链这个我还是看过的。但还是A不掉,没明确神魔意思 。总而言之。大牛的博客是个好东西。我就那么看了一下,还是不懂怎莫办啊,哎,就那样就A掉了。

    。。。

    。。

    今天我们来谈一下这个并查集的删除操作,依据我对大牛的理解啊,这个并查集的删除操作并非把原来的节点删除掉,而是用一个替身替掉,如今的这个点仅仅是用作桥梁的作用,即是没用的,del  ,,,del  ,。。。删除,那些被删掉的就从n開始给他们一个地址,然后即例如以下代码所看到的
    比方说如上图。还没有并到5之前,要删除节点4。假设直接把4直接删除掉的话,那么4上的关系所有删除了。1,3就不在一个集合,可是还要他们在一个集合。那么就给4一个虚拟的节点,在接下来把虚拟节点就是1,3的父节点了,可是这样并非正确的,那么就在和5并起来的时候,把它们各自的虚拟节点并上去 。由于初始化的时候他们的虚拟节点也是他们本身。所以它们最后还是并到了一个集合。根节点还是5.有可能也是虚拟的节点。这都不重要,可是1,3的关系没有变。
    假如已经变为上面的那个图了。把4删除掉之后。给他一个新的虚拟节点之后。可是他本身还在这边,相当于一个一个桥连接着。仅仅是他的父节点已经变了。可是其它的还在这里面。

    也就是说已经成功的把它删除了,他已经属于还有一个集合了

    下面是測试数据
    5 6
    M 0 1
    M 1 2
    M 1 3
    S 1
    M 1 2
    S 3


    #include <stdio.h>
    #include <string.h>
    #define N 100001
    #define M 1000001
    int par[N+M+50];
    int repplace[N+50];
    int flag[N+M];
    int ind;
    void  init(int n )
    {
      for(int i=0;i<n;i++)
      {
        par[i]=i;
        repplace[i]=i;
      }
      ind =n;
    }
    int findset(int n)
    {
    	if(n==par[n])
    		return n;
    	else
            return par[n]=findset(par[n]);
    }
    void  unite(int n,int m)
    {
    	int pn=findset(n);
    	int pm=findset(m);
    	if(pn!=pm)
    		par[pn]=pm;
    }
    void Delete(int n)//删除操作。
    {
    	repplace[n]=ind;
    	par[ind]=ind;
    	ind++;
    }
    int main()
    {
    	int a,b;
    	char s[3];
    	int x,y;
    	int cas=0;
    	while(scanf("%d%d",&a,&b)==2)//我一直纠结为什莫会WA。推断输入的控制条件错了
    	{  
    	    if(a==0&&b==0)
                break;
    		init(a);
            for(int i=0;i<b;i++)
            {
            	scanf("%s",s);
            	if(s[0]=='M')
            	{
                   scanf("%d%d",&x,&y);
                   unite(repplace[x],repplace[y]);
            	}
            	else
            	{
                   scanf("%d",&x);
                   Delete(x);
            	}
            }
            memset(flag,0,sizeof(flag));
            int ans=0;
            for(int i=0;i<a;i++)//推断他们有几个集合
            {
                  int hh=findset(repplace[i]);
                  if(!flag[hh])
                  {
                     flag[hh]=1;
                     ans++;
                  }
            }
             printf("Case #%d: %d
    ",++cas,ans);
    	}
    }
    
    
    其他就不做介绍了,仅仅要会并查集的一般能看懂看懂。看不懂可评论。或发私信。。。

    。。

  • 相关阅读:
    Python:三元运算
    SaltStack部署服务及配置管理apache+php-第二篇
    SaltStack介绍及简单配置-第一篇
    git基础常用维护命令
    MySQL设置只读模式
    运维杂记-05
    Tomcat的配置,设置内存,获取用户IP
    Linux系统巡检项目
    Redis维护
    nginx配置文件说明
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5337493.html
Copyright © 2011-2022 走看看