您的位置:首页 > 其它

zoj 3761 Easy billiards 并查集+dfs

2014-03-06 11:23 239 查看
生活真是奇妙的东西,这样的题目居然能被联想到这样的算法,只能说智商不够啊。

这道题目的意思不解释了,月赛的时候我队友已经想出来了做法,但是我们最后还是没A。

题解:

1。首先将所有能连接的球连接起来,然后看这个图有几个连通分量,那最后就会剩下几个球,这个用并查集实现下就好了。

由于xi,yi坐标比较分散所以要用邻接表进行存储。

2. 接下来就是输出方案,本来我们是想考虑点的度的,后来发现实现起来有点困难,实际上只需要按照并查集的唯一的头,进行深度优先搜索,这样就形成了一颗深搜树,

然后再用叶子节点打他的根节点就可以了。这样一次能打掉所有叶子节点(简直神奇)。

3.一开始进行2次排序,进行点的连接。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int e,head[10005],root[10005],vis[10005];
struct node
{
int x,y;
int nod,l;
}s[10005],q[10005];

struct lj
{
int v;
int next;
}nn[10005];
int cmp1(struct node a,struct node b)
{
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}

int cmp2(struct node a,struct node b)
{
if(a.y==b.y) return a.x<a.x;
return a.y<b.y;
}

void link(int u,int v)
{
nn[e].v=v;
nn[e].next=head[u];
head[u]=e++;
}

int find(int x)
{
if(x==root[x]) return x;
else return root[x]=find(root[x]);
}

void dfs(int x)
{
int k;
for(k=head[x];k!=-1;k=nn[k].next){
int v=nn[k].v;
if(!vis[v]){
vis[v]=1;
if(q[v].x==q[x].x){
if(q[v].y<q[x].y)
q[v].l=4;
else
q[v].l=3;
}
if(q[v].y==q[x].y){
if(q[v].x<q[x].x)
q[v].l=2;
else
q[v].l=1;
}
dfs(v);
}
}
if(q[x].l==4) printf("(%d, %d) UP\n",q[x].x,q[x].y);
else if(q[x].l==3) printf("(%d, %d) DOWN\n",q[x].x,q[x].y);
else if(q[x].l==2) printf("(%d, %d) RIGHT\n",q[x].x,q[x].y);
else if(q[x].l==1) printf("(%d, %d) LEFT\n",q[x].x,q[x].y);
}

int main()
{
int n,i;
while(scanf("%d",&n)!=EOF){
e=1;
memset(head,-1,sizeof(head));
for(i=0;i<n;i++){
scanf("%d %d",&s[i].x,&s[i].y);
q[i].x=s[i].x;q[i].y=s[i].y;
q[i].nod=s[i].nod=i;
q[i].l=s[i].l=-1;
}
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++) root[i]=i;
sort(s,s+n,cmp1);
for(i=1;i<n;i++){
if(s[i].x==s[i-1].x){
link(s[i].nod,s[i-1].nod);
link(s[i-1].nod,s[i].nod);
int ra=find(s[i].nod);
int rb=find(s[i-1].nod);
if(ra!=rb) root[rb]=ra;
}
}
sort(s,s+n,cmp2);
for(i=1;i<n;i++){
if(s[i].y==s[i-1].y){
link(s[i].nod,s[i-1].nod);
link(s[i-1].nod,s[i].nod);
int ra=find(s[i].nod);
int rb=find(s[i-1].nod);
if(ra!=rb) root[rb]=ra;
}
}
int ans=0,father[3000];
for(i=0;i<n;i++){
if(root[i]==i){
father[ans++]=i;
}
}
printf("%d\n",ans);
for(i=0;i<ans;i++){
vis[father[i]]=1;
dfs(father[i]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: