题目链接:http://www.patest.cn/contests/mooc-ds/04-2
题目分析:这是一道考察“并查集”的问题,通过的人像2-1一样那么少。
首先输入的是一个整型数,代表网络中有多少个结点。
然后输入若干行,每行由1个字符,两个整数组成,字符为I代表增加连接,字符为C代表检查是否连接,字符为S代表结束输入。
每个字符为C检查连接的时候,要输出yes或者no说明是否连通。
最后要输出整个网络的情况,如果全部连通则输出The network is connected.,否则输出有多少个点没有连通。
特别说明:这道题比较坑爹,需要有几个点特别注意一下:
1) 如果你用老师给的Find函数,那你就废废了,那个函数的时间复杂度绝对不能让你AC。不仅吐槽一下。必须要自己写一个,很简单,代码如下:
int Find( ElementType X )
{
if(S[X]==X)
return X;
return S[X]=Find(S[X]);
}
2) 不需要像课上讲的一样,定义一个结构体,一个是数据区,一个是父结点区,只用一个一维数组就够了!为了方便,我们定义数组的长度比正常的大1,这样方便我们从1开始查起。
// 全局变量定义
int *S;
// 在main函数中动态申请
S = new int[num+1];
3) Union的时候不需要考虑哪个子树大,哪个子树小,并不影响你AC。但是如果考虑的话更好,到底能提高多少速度自己实践下就知道了。
void Union( ElementType X1, ElementType X2)
{
int Root1, Root2;
Root1 = Find(X1);
Root2 = Find(X2);
if ( Root1 != Root2 )
{
if(S[Root1] < S[Root2])
{
S[Root2] = Root1;
}
else
{
S[Root1] = Root2;
}
}
}
代码分析:
头文件及全局变量声明:1~5行。这里我们用ElementType代替int,是因为从老师那里拷的算法,用的就是ElementType,各位编写的时候无视就可以了。
Find函数和Union函数:6~30行。上面已经详细说过了,各位看看就好。
主函数输入及输出:31~65行。虽然看起来比较多,但是还是很简单的。
#include <iostream>
#define ElementType int
using namespace std;
int *S;
int Find( ElementType X )
{
if(S[X]==X)
return X;
return S[X]=Find(S[X]);
}
void Union( ElementType X1, ElementType X2)
{
int Root1, Root2;
Root1 = Find(X1);
Root2 = Find(X2);
if ( Root1 != Root2 )
{
if(S[Root1] < S[Root2])
{
S[Root2] = Root1;
}
else
{
S[Root1] = Root2;
}
}
}
int main()
{
int num;
cin >> num;
char choose;
int c1, c2;
S = new int[num+1];
for(int i=0; i<=num; i++) // 初始化
S[i] = i;
while(1)
{
cin >> choose;
if(choose == 'S')
break;
cin >> c1 >> c2;
if(choose == 'I')
Union(c1, c2);
if(choose == 'C')
{
if(Find(c1) == Find(c2))
cout << "yes" << endl;
else
cout << "no" << endl;
}
}
int icount=0;
for(int i=1; i<=num; i++)
if(S[i] == i) // 如果Parent就它自己,证明是根结点
icount++;
if(icount == 1)
cout << "The network is connected." << endl;
else
cout << "There are " << icount << " components." << endl;
return 0;
}
文章转载自http://www.cnblogs.com/clevercong/p/4192953.html