HDU_Virtual Friends (并查集)

 

 /*贡献出无数WA, 就因为一个地方写错, 悲剧的一晚上啊!不过能过了还是很爽的。

  思路:用Trie树给字符串重新标号,然后用并查集,用一个a[i] 记录当前并查集跟结点上连接的结点数。*/



#include
<iostream>
#include
<cstdio>
#include
<cstring>

using namespace std;

struct node
{
int flag;
node
* next[53];
};

const int N = 200005;

int parent[N];
int rank[N];
int a[N];
int num;

node
* newnode()
{
node
*p = new node;
p
->flag = 0;
for(int i = 0; i < 52; i++)
p
->next[i] = NULL;
return p;
}

int insert(node *root, char *s)
{
node
*p = root;
int i, len = strlen(s), t;
for(i = 0; i < len; i++)
{
if(isupper(s[i]))
t
= s[i] - 'A';
else
t
= s[i] - 'a' + 26;

if(p->next[t] == NULL)
p
->next[t] = newnode();
p
= p->next[t];
}
if(p->flag)
return p->flag;
else
{
p
->flag = num++;
return p->flag;
}
}

void del(node *p)
{
if(p)
{
for(int i = 0; i < 52; i++)
if(p->next[i])
del(p
->next[i]);
}
delete p;
p
= NULL;
}

void init()
{
for(int i = 0; i < N; i++)
{
parent[i]
= i;
a[i]
= 1;
}
}
int find(int x)
{
int k = x, r = x, j;
while(r != parent[r])
r
= parent[r];
while(k != r)
{
j
= parent[k];
parent[k]
= r;
k
= j;
}
return r;
}

void union_set(int x, int y)
{
x
= find(x);
y
= find(y);

if(x == y) return ;

parent[x]
= y;
a[y]
+= a[x];
}

int main()
{
//freopen("data.in", "r", stdin);

int t, n, x, y;
char s1[35], s2[35];

node
* root;

while(scanf("%d", &t) != EOF)
{
while(t--)
{
scanf(
"%d", &n);

if(n == 0)
{
printf(
"0\n");
continue;
}

init(); num
= 1;
root
= newnode();

while(n--)
{
scanf(
"%s%s", s1, s2);

x
= insert(root, s1);
y
= insert(root, s2);

union_set(x, y);
printf(
"%d\n", a[find(y)]);  //一直写成a[y],贡献出无数WA!!!
            }
del(root);
}
}
return 0;
}

  

原文地址:https://www.cnblogs.com/vongang/p/2175327.html