并查集第一题 思路分析 poj2236
开始训练并查集 这是做并查集第一题 所以做一个思路分析 有助于自己对并查集的理解
题意就不解释了
问题一 判断各个节点之间是否可达?
很明显 这里可以用dfs 或者 并查集 进行判断 这里用并查集比较快 因为这里并不用用到两点之间的路劲(由于比较慢,所以不用路劲来进行解决)或者其他一些信息
一开始做的时候 因为是先进行各个点之间用并查集单独进行连通 到了后面的修复操作就不知道该怎样在并查集中进行修复操作 如果节点的修复操作设为true 就代表这个节点可以被这个节点所在的集合中的其他节点直接访问 但是一个集合的节点在原图中可以是间接相连的,所以上面的操作就是有问题的
问题二 修复操作在上面的并查集中该怎样做?
上面是先判断可达在就行修复,这个是有问题的,其实是反过来做,先进行修复操作,然后再根据修复的节点,便利之前所操作的节点,看是是否可达,如果可达就说明集合中的任何节点都与这个节点相互连通,既可以测试成功,就加入这个节点到集合中
总结
是先确定修复 在建立并查集 从这个便可以看出 要先确定元素中的关系才用并查集维护关系 而并查集中的元素是相互可达的 只有这样的关系才能加入并查集 因为是第一次做并查集 所以这道题想了很久 一开始的思路就错了 导致后面的都错了 看来并查集应用的思想自己还没弄懂 得要多思考 多换角度想啊
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
#define INF 0xfffffff//跑了3000多秒 有点慢 这里询问是300000 所以在计算两点之间距离时
int N,D,x,y;//花费了很多的时间 可以用个预处理处理二维数组存储距离
struct node{
bool rep;
int x,y;
}mp[1005];int pa[1005];
double distants(node a,node b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int findset(int x)
{
return pa[x]==x?x:pa[x]=findset(pa[x]);//带路径压缩
}
int unite(int x,int y)
{
int px=findset(x);
int py=findset(y);
if(px!=py)
if(distants(mp[x],mp[y])<=(double)D)
pa[py]=px;
}
int main()
{
char op;
scanf("%d%d",&N,&D);
for(int i=1;i<=N;i++)
{
pa[i]=i;
scanf("%d%d",&mp[i].x,&mp[i].y);
mp[i].rep=false;
}
while(scanf(" %c",&op)!=EOF)
{
int a,b;
if(op=='O')
{
scanf("%d",&a);
mp[a].rep=true;
for(int i=1;i<=N;i++)
{
if(i!=a && mp[i].rep==true)
unite(i,a);
}
}
else
{
scanf("%d%d",&a,&b);
if(findset(a)==findset(b))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}
第二种
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
#define INF 0xfffffff//跑了3000多秒 有点慢 这里询问是300000 所以在计算两点之间距离时
int N,D,x,y;//花费了很多的时间 可以用个预处理处理二维数组存储距离
struct node{
bool rep;
int x,y;
}mp[1005];int pa[1005];
double distants(node a,node b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int findset(int x)
{
return pa[x]==x?x:pa[x]=findset(pa[x]);//带路径压缩
}
int unite(int x,int y)
{
int px=findset(x);
int py=findset(y);
if(px!=py)
if(distants(mp[x],mp[y])<=(double)D)
pa[py]=px;
}
int main()
{
char op;
scanf("%d%d",&N,&D);
for(int i=1;i<=N;i++)
{
pa[i]=i;
scanf("%d%d",&mp[i].x,&mp[i].y);
mp[i].rep=false;
}
while(scanf(" %c",&op)!=EOF)
{
int a,b;
if(op=='O')
{
scanf("%d",&a);
mp[a].rep=true;
for(int i=1;i<=N;i++)
{
if(i!=a && mp[i].rep==true)
unite(i,a);
}
}
else
{
scanf("%d%d",&a,&b);
if(findset(a)==findset(b))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
#define INF 0xfffffff//好像没快多少
int N,D,x,y;//
struct node{
bool rep;
int x,y;
}mp[1005];int pa[1005];
double dist[1005][1005];
double distants(node a,node b)
{
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int findset(int x)
{
return pa[x]==x?x:pa[x]=findset(pa[x]);//路劲压缩
}
int unite(int x,int y)
{
int px=findset(x);
int py=findset(y);
if(px!=py)
if(dist[x][y]<=(double)D)
pa[py]=px;
}
int main()
{
char op;
scanf("%d%d",&N,&D);
for(int i=1;i<=N;i++)
{
pa[i]=i;
scanf("%d%d",&mp[i].x,&mp[i].y);
mp[i].rep=false;
}
for(int i=1;i<=N;i++)
{
for(int j=i-1;j>=1;j--)
{
dist[i][j]=distants(mp[i],mp[j]);
dist[j][i]=dist[i][j];
}
}
while(scanf(" %c",&op)!=EOF)
{
int a,b;
if(op=='O')
{
scanf("%d",&a);
mp[a].rep=true;
for(int i=1;i<=N;i++)
{
if(i!=a && mp[i].rep==true)
unite(i,a);
}
}
else
{
scanf("%d%d",&a,&b);
if(findset(a)==findset(b))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}