hdu 2473

来源:互联网 发布:java实现iis域认证 编辑:程序博客网 时间:2024/06/17 15:49

一道需要虚拟父节点的并查集题。在处理初始化数组是借鉴了别人的思路。在delete时增加需要的节点。

#include<cstdio>#include<cstring>const int maxn = 1e6 + 5;int pre[maxn], id;int fictitious[maxn];int Rank[maxn];void init(int x){    //printf("%d\n", x);    for(int i = 0; i <= x; i++)        pre[i] = fictitious[i] = i;    memset(Rank, 0, sizeof(Rank));    id = x;}/*int root(int x){    int i, j = x;    while(j != pre[j])    {        j = pre[j];    }    while(x != j)    {        i = pre[x];        pre[x] = j;        x = i;    }    return j;}*/int root(int x){    if(x != pre[x])        pre[x] = root(pre[x]);    return pre[x];}void merge_set(int x, int y){    int fx = root(x);    int fy = root(y);    if(fx != fy)    {        pre[fx] = fy;    }}void set_delete(int x){    pre[id] = id;    fictitious[x] = id++;}int main(){    int n, m, kase = 1;    while(scanf("%d%d", &n, &m) && (m || n))    {        init(n);        while(m--)        {            char s[3];            scanf("%s", s);            if(s[0] == 'M')            {                int t1,t2;                scanf("%d%d", &t1, &t2);                //printf("%d %d\n", fictitious[t1], fictitious[t2]);                merge_set(fictitious[t1], fictitious[t2]);            }            else            {                int temp;                scanf("%d", &temp);                set_delete(temp);            }        }        int ans = 0;        for(int i = 0; i < n; i++)        {            int pos = root(fictitious[i]);            if(Rank[pos] == 0)            {                Rank[pos] = 1;                ans++;            }        }        printf("Case #%d: %d\n", kase++, ans);    }    return 0;}



原创粉丝点击