POJ 1308 Is It A Tree?

在此提供了两种解法:(1)利用树的性质,除了根节点入度为0外,其余节点入度均为1;(2)利用并查集,但是并查集检测是否存在多余的边后,还要检测全部节点构成的是树还是森林。比如测试数据 1 2 2 3 4 5 0 0。

Solution 1:

#include <iostream>
#include <vector>

using namespace std;

const int MAXSIZE = 10024;
vector<int> degree;
vector<bool> flags;

int main()
{
    int k = 0;
    int u, v;
    while( (cin >> u >> v) && (~u || ~v) )
    {
	degree.assign(MAXSIZE, 0);
	flags.assign(MAXSIZE, false);

	++k;
	degree[v]++;
	flags[u] = true;
	flags[v] = true;

	if( !u && !v )
	{
	    cout << "Case " << k << " is a tree." << endl;
	    continue;
	}

	while( (cin >> u >> v) && (u || v) )
	{
	    degree[v]++;
	    flags[u] = true;
	    flags[v] = true;
	}
	// Judge
	int cnt0 = 0, cnt1 = 0;
	int n = 0;
	int i;
	for(i = 0; i < MAXSIZE; ++i)
	{
	    if( flags[i] )
	    {
		++n;
		if( degree[i] == 1 )
		    ++cnt1;
		else if( degree[i] == 0 )
		    ++cnt0;
		else break;
	    }
	}
	if(i == MAXSIZE && cnt0 == 1 && cnt1 == n-1)
	    cout << "Case " << k << " is a tree." << endl;
	else cout << "Case " << k << " is not a tree." << endl;
    }
    return 0;
}

Solution 2:

#include <iostream>
#include <vector>

using namespace std;

const int MAXSIZE = 10024;
int k = 0;
vector<int> p, r;
vector<bool> vex;

void MakeSet()
{
    p.clear();
    p.resize( MAXSIZE );
    r.assign(MAXSIZE, 0);
    for(int i = 0; i < MAXSIZE; ++i)
	p[i] = i;
}

int FindSet(int c)
{
    if(p[c] != c)
	p[c] = FindSet(p[c]);
    return p[c];
}

void Union(int lc, int rc)
{
    int lp = FindSet(lc);
    int rp = FindSet(rc);
    if( r[lp] < r[rp] )
	p[lp] = rp;
    else 
    {
	p[rp] = lp;
	r[lp]==r[rp]?r[lp]++:NULL;
    }
}

int main()
{
    int u, v;
    while( (cin >> u >> v) && (~u || ~v) )
    {
	++k;
	if( !u && !v )
	{
	    cout << "Case " << k << " is a tree." << endl;
	    continue;
	}

	MakeSet();
	vex.assign(MAXSIZE, false);

	bool ans = true;
	do
	{
	    if( ans )
	    {
		vex[u] = true;
		vex[v] = true;

		if(FindSet(u) != FindSet(v))
		    Union(u, v);
		else
		    ans = false;
	    }
	}while( (cin >> u >> v) && (u || v) );

	if( ans )
	{
	    int s = -1;
	    for(int i = 0; i < MAXSIZE; ++i)
		if( vex[i] )
		{
		    if( s == -1 )
			s = FindSet( i );
		    else if( s != FindSet(i) )
		    {
			ans = false;
			break;
		    }
		}
	}

	cout << "Case " << k << (ans?" is a tree.":" is not a tree.") << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值