并查集还是很好理解的,应用在求联通块,儿子们找同一个祖先的问题,现在我并查集代码还有点问题的,具体优化还需要继续学习。
用poj的题目(2236)讲一下就行了把应该。=2236
Description
An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network with the lap computers, but an unexpected aftershock attacked, all computers in the network were all broken. The computers are repaired one by one, and the network gradually began to work again. Because of the hardware restricts, each computer can only directly communicate with the computers that are not farther than d meters from it. But every computer can be regarded as the intermediary of the communication between two other computers, that is to say computer A and computer B can communicate if computer A and computer B can communicate directly or there is a computer C that can communicate with both A and B.Input
The first line contains two integers N and d (1 <= N <= 1001, 0 <= d <= 20000). Here N is the number of computers, which are numbered from 1 to N, and D is the maximum distance two computers can communicate directly. In the next N lines, each contains two integers xi, yi (0 <= xi, yi <= 10000), which is the coordinate of N computers. From the (N+1)-th line to the end of input, there are operations, which are carried out one by one. Each line contains an operation in one of following two formats:Output
For each Testing operation, print "SUCCESS" if the two computers can communicate, or "FAIL" if not.Sample Input
4 1 0 1 0 2 0 3 0 4 O 1 O 2 O 4 S 1 4 O 3 S 1 4
Sample Output
FAIL SUCCESS
题目意思是电脑有几个是坏的,给你一个数,表示每个没坏的电脑之间能通信的最大距离,O操作是让一个电脑有用,S问这两个电脑能不能通信,通过别的电脑做桥梁也行。
代码:
#include<iostream>
using namespace std;
//int fa[1005],x[1005],y[1005];
struct ss
{
int x,y,ft,fa;
}s[1005];
int fi(int x)
{
if(s[x].fa==x) return x;//fa[x];
s[x].fa=fi(s[x].fa);
}
void unions(int cs1,int cs2,int juli)
{
int p1=fi(cs1);
int p2=fi(cs2);
if((s[cs1].x-s[cs2].x)*(s[cs1].x-s[cs2].x)+ (s[cs1].y-s[cs2].y)*(s[cs1].y-s[cs2].y)<=juli*juli)
s[p2].fa=p1;
//cout<<"sssssss"<<s[1].fa<<s[2].fa<<s[3].fa<<s[4].fa<<endl;
}
void checks(int x,int y)
{
if(fi(x)!=fi(y))
cout<<"FAIL"<<endl;
else
cout<<"SUCCESS"<<endl;
}
int main( )
{
int i,n,juli,a,b;
char ch;
cin>>n>>juli;
for(i=1;i<=n;i++)
{
s[i].fa=i;
s[i].ft=0;
}
for(i=1;i<=n;i++)
cin>>s[i].x>>s[i].y;
while(cin>>ch)
{
if(ch=='O')
{
cin>>a;
s[a].ft=1;
for(i=1;i<=n;i++)
if(s[i].ft==1&&i!=a)
unions(i,a,juli);
}
else if(ch=='S')
{
cin>>a>>b;
checks(a,b);
}
}
return 0;
}
然后并查集主要是定义一个结构体再写几个函数:
find(避免重名我写成fi)函数:
int fi(int x)
{
if(s[x].fa==x) return x; //fa[x];
s[x].fa=fi(s[x].fa);
}
//这个函数主要的功能是找x的爸爸,如果x的爸爸 s[x].fa 就是他自己的话就返回x自己。如果不是的话,就递归找下去,让x的爸爸等于 他爸爸的爸爸。 认他爷爷做爸爸,如果再不是...........这里需要停下来仔细推导下过程。
union(~unios)函数:
void unions(int cs1,int cs2,int juli)
{
int p1=fi(cs1);
int p2=fi(cs2);
if((s[cs1].x-s[cs2].x)*(s[cs1].x-s[cs2].x)+ (s[cs1].y-s[cs2].y)*(s[cs1].y-s[cs2].y)<=juli*juli)
s[p2].fa=p1;
//cout<<"sssssss"<<s[1].fa<<s[2].fa<<s[3].fa<<s[4].fa<<endl;
}
//这个函数呢,就是联合函数啦,首先!这个int p1=fi(cs1),p2=fi(cs2),是非常重要的,是更新祖先的,之前写我一直忘记,搞的我很难受,后面的if是根据题目需要来写的,上面是如果cs1,cs2这两个点的距离小于题目给的数据,就让cs1和cs2的祖先变成一样的,上面是让cs2的祖先变成cs1的祖先。
check 函数:这个函数相比上面那两个函数就不是那么重要了。也是根据个人习惯和题目来的,写不写无所谓。
void checks(int x,int y)
{
if(fi(x)!=fi(y))
cout<<"FAIL"<<endl;
else
cout<<"SUCCESS"<<endl;
}
然后再说下主函数需要处理的数据初始化。
for(i=1;i<=n;i++)
{
s[i].fa=i;
s[i].ft=0;
}
// 很简单,就是开始让每个人认做他自己的爹,或者说每个人认他自己做爹。s[i].ft的作用是用来标记的。
嗯,应该没有什么问题了。
再贴个模版题,嘻嘻:hdu 1213:
题目就不放了 传送门:.php?pid=1213
代码:
#include<iostream>
using namespace std;
int fa[1005];
int fi(int x)
{
if(fa[x]==x)
return fa[x];
fa[x]=fi(fa[x]);
}
void unio(int x,int y)
{
x=fi(x);
y=fi(y);
if(fa[x]!=fa[y])//if(x!=y)
fa[x]=y;
}
int check(int x,int y)
{
if(fi(x)==fi(y))
return 1;
else
return 0;
}
int main( )
{
int t,i,j,n,m,x,y,ans;
cin >> t;
while(t--)
{
cin>>n>>m;
for(i=1;i<=n;i++)
fa[i]=i;
for(j=0;j<m;j++)
{
cin>>x>>y;
unio(x,y);
//cout << fa[1] <<endl;
}
ans=0;
for(j=1;j<=n;j++)
if(fa[j]==j) ans++;
cout<<ans<<endl;
}
return 0;
}
最后就判断有几个人认他自己做祖先,就有几个联通块了。
转载于:.html
本文发布于:2024-01-29 20:24:36,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170653108018053.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |