Hdu1232畅通工程 解题报告

并查集:将编号分别为1到n的n个对象划分为不相交集合,在每个集合中,选择其中某个元素代表所在集合。主要有两个操作:(1)合并两个集合,(2)查找某元素属于哪个集合。下面是利用并查集求解Hdu 1232 畅通工程(http://acm.hdu.edu.cn/showproblem.php?pid=1232),比用dfs,bfs搜索大大提高了时间效率。

#include <iostream>

#include <vector>

using namespace std;



vector <int> parents;



int findSet(int i)//if (parents[i]==i) then i is root;else if (parents[i]==j(j!=i)) then j is root.

{

	int root=i;



	while(root != parents[root]) //after loop get root

	{

		root=parents[root];

	}



	int k=i;



	while(k != root) //path compression

	{

		int t=parents[k];

		parents[k]=root;

		k=t;

	}



    return root;

}



void unionSet(int a, int b)//union a,b to the small parent

{

	int j=findSet(a);

	int k=findSet(b);



	if (j==k) return;

	

	if (j<k)

	{

		parents[k]=j;

	}

	else

	{

		parents[j]=k;

	}

}



bool run()

{

    int n,m,i;

    

	cin>>n;

	if (n==0) return false;



	cin>>m;



	parents.resize(n+1);



	for(i=1;i<=n;i++)

	{

		parents[i]=i; //init ,each i is a tree

	}



    for(i=0;i<m;i++)

    {

        int a,b;

       

		cin>>a>>b;	



		unionSet(a,b);

    }



	int cntRoot=0;



	for(i=1;i<=n;i++)

	{

		if (i==parents[i]) //count subtrees

		{

			cntRoot++;

		}

	}



	cout << cntRoot-1 << endl;



	return true;

}



int main()

{

	while(run());

	return 0;

}

说明:while(k != root) //把i开始结点的根修改为找到的根root,路径压缩便于提高效率

阅读更多

没有更多推荐了,返回首页