一、解决前的代码
#include "string.h"
# include<iostream>
using namespace std;
#define MAXN 50000
int fa[MAXN];
int find(int i)
{
int r;
for (r = i;fa[r] >= 0;r = fa[r]);
while (i != r)
{
int s = fa[i];
fa[i] = r;
i = s;
}
return r;
}
void merge(int i, int j)
{
int x = find(i), y = find(j);
int temp = fa[x] + fa[y];
if (fa[x] < fa[y])
{
fa[y] = x;
fa[x] = temp;
}
else
{
fa[x] = y;
fa[y] = temp;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
while (cin >> n >> m)
{
if ((m + n) == 0)break;
memset(fa, -1, sizeof(fa));
while (m--)
{
int num, a, b;
cin >> num >> a;
while (--num)
{
cin >> b;
merge(a, b);
}
}
cout << -fa[find(0)] << "\n";
}
system("pause");
return 0;
}
二、问题所在
上网查了很多资料,说zoj中的Segmentation Fault 就是runtime error 。
可能的问题有:
(1)修改了常量字符串的值。
(2)指针/数组越界
(3)数组开大或开小
但是我觉得我的程序都不存在这些问题。后来认真看了一下是merge函数出了问题。
如果(x==y)的话,即i和j在同一个并查集里,temp的值就会比真实值大了(是真实值的两倍)。在极端的测试条件下temp的值会非常大。
三、修改后的代码
发现问题后,修改其实很简单。在merge里面加个if语句判断x是否等于y即可。
#include "string.h"
# include<iostream>
using namespace std;
#define MAXN 50000
int fa[MAXN];
int find(int i)
{
int r;
for (r = i;fa[r] >= 0;r = fa[r]);
while (i != r)
{
int s = fa[i];
fa[i] = r;
i = s;
}
return r;
}
void merge(int i, int j)
{
int x = find(i), y = find(j);
int temp = fa[x] + fa[y];
if(x!=y){
if (fa[x] < fa[y])
{
fa[y] = x;
fa[x] = temp;
}
else
{
fa[x] = y;
fa[y] = temp;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
while (cin >> n >> m)
{
if ((m + n) == 0)break;
memset(fa, -1, sizeof(fa));
while (m--)
{
int num, a, b;
cin >> num >> a;
while (--num)
{
cin >> b;
merge(a, b);
}
}
cout << -fa[find(0)] << "\n";
}
system("pause");
return 0;
}