现在的位置: 首页 > 综合 > 正文

hdu2473 Junk-Mail Filter

2018年04月23日 ⁄ 综合 ⁄ 共 1003字 ⁄ 字号 评论关闭

并查集删点问题,牺牲空间换取时间,就是给每一个点找一个替代,删除的时候只需要把替代更换就可以了

code:

#include <cstdio>
#include <cstring>
using namespace std;

const int INF = 0x3fffffff;

int n,m,fa[1000000],rank[100000],rep[1000000],ind;
bool vis[1100000];

void init()
{
    for(int i=0;i<n;i++)
    {
        fa[i]=i;
        rank[i]=0;
        rep[i]=i;//刚开始i的代替就是i自己
    }
    ind=n;
}
int find(int k)
{
    if(k!=fa[k])
    {
        fa[k]=find(fa[k]);
    }
    return fa[k];
}
void merge(int x,int y)
{
    if(x==y)
    {
        return ;
    }
    if(rank[x]<rank[y])
    {
        fa[x]=y;
    }else{
        fa[y]=x;
        if(rank[x]==rank[y])
        {
            rank[x]++;
        }
    }
}
void del(int k)//替代删除,只更改它的替代就可以
{
    rep[k]=ind;
    fa[ind]=ind;//初始化集合
    ind++;
}

char c;
inline void scan(int &x){
    while(c=getchar(),c<'0'||c>'9');
    x=c-'0';
    while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';
}

int main()
{
    int cas=0,a,b,i;
    char buf;
    while(~scanf("%d%d",&n,&m) && (n || m))
    {
        init();
        getchar();
        for(i=1;i<=m;i++)
        {
            buf=getchar();
            if(buf=='M')
            {
                scan(a);
                scan(b);
                a=find(rep[a]);
                b=find(rep[b]);
                merge(a,b);
            }else{
                scan(a);
                del(a);
            }
        }
        b=0;
        memset(vis,false,sizeof(int)*(ind+1));
        for(i=0;i<n;i++)
        {
            a=find(rep[i]);
            if(!vis[a])
            {
                b++;
                //printf("%d\n",a);
                vis[a]=true;
            }
        }
        printf("Case #%d: %d\n",++cas,b);
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.