您的位置:首页 > 其它

暑假训练专题二 并查集的理解 优先队列

2012-07-02 21:08 429 查看
并查集主要是体现在并和查的概念上,这个很重要,判断两个元素是否属于同一个集合,将属于不同的集合合并,不合并不属于相同的集合,这样就可以了。

对于集合个数的判断: 主要是要找的这个节点的parent值是否等于自身,x==p[x].parent,如果相等则成立。

今天做了 3道并查集的问题~~

了解了并查集用到的三个子函数,很有用:

1:数组数据的初始化。

void Make_set()
{
int i;
for(i=0;i<n;i++)
{
p[i].data=i;
p[i].rank=0;
p[i].parent=i;
}
}


2:优化后对树的根结点的查找。

int Find(int x)
{
if(x!=p[x].parent) p[x].parent=Find(p[x].parent);
return p[x].parent;
}


3:优化后的合并树,是按照秩(树的高度)来合并的。

void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x!=y){
if(p[x].rank>p[y].rank){p[y].parent=x;}
else {
p[x].parent=y;
if(p[x].rank==p[y].rank)p[y].rank++;
}
}
}


这是用到的三个代码模版。

下面开始 对例题尽心分析。

杭电1232 畅通工程 就是对并查集的简单应用。

#include<stdio.h>
#include<string.h>
typedef struct node{
int data;
int rank;
int parent;
}UFSTree;
UFSTree p[1010];

void Make_set(int n);
int Find(int x);
void Union(int x,int y);
int a[1010];
int main()
{
int n,m,road1,road2,i,j,k,num,flag;
while(scanf("%d %d",&n,&m)&&n!=0)
{
if(m==0){printf("%d\n",n-1);continue;}
Make_set(n);
for(i=1;i<=m;i++)
{
scanf("%d %d",&road1,&road2);
Union(road1,road2);
}
j=0;
memset(a,0,sizeof(a));
a[j]=Find(1);j++;

for(i=2;i<=n;i++)
{
flag=0;
num=Find(i);

for(k=0;k<j;k++)
{
if(a[k]==num){flag=1;break;}
}
if(flag==0){a[j]=num;j++;}
}

printf("%d\n",j-1);

}

}

void Make_set(int n)
{
int i;
for(i=1;i<=n;i++)
{
p[i].data=i;
p[i].rank=0;
p[i].parent=i;
}
}

int Find(int x)
{
if(x!=p[x].parent) p[x].parent=Find(p[x].parent);
return p[x].parent;
}

void Union(int x,int y)
{

x=Find(x);
y=Find(y);

if(x!=y){
if(p[x].rank>p[y].rank){p[y].parent=x;}
else {
p[x].parent=y;
if(p[x].rank==p[y].rank){
p[y].rank++;
}
}
}
}


还有就是 poj 2524 Ubiquitous Religions和 这道题完全类似。

还有一道是 poj The Suspects 有略微的变型~~要注意。

优先队列:

是按从大到小的顺序输出的。

直接进行输入输出,进行排序;

#include<iostream>
#include<queue>
using namespace std;
int main()
{
int a[10]={4,3,2,5,4,2,3,2,10,9},i;
priority_queue<int> qi;
for(i=0;i<10;i++)
{
qi.push(a[i]);
}
for(i=0;i<10;i++)
{
cout<<qi.top()<<" ";
qi.pop();
}
}


得出的结果:



下面是对其尽心逆着排序:即从小到大输出:

#include<iostream>
#include<queue>
using namespace std;
int main()
{
priority_queue<int ,vector<int>, greater<int> >  q2;
int i,a[9]={4,3,2,1,5,6,7,8,9};
for(i=0;i<9;i++)
{
q2.push(a[i]);
}
for(i=0;i<9;i++)
{
cout<<q2.top()<<" ";
q2.pop();
}

cin>>a[i];
}


下面是对两组数据的排序:

根据关键字来进行排序;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: