博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VIJOS P1540 月亮之眼
阅读量:5153 次
发布时间:2019-06-13

本文共 2355 字,大约阅读时间需要 7 分钟。

【题目大意】

         有多个珠子,给出部分珠子之间的相对上下位置和间距,问你这些珠子在满足给出的条件下,是否能把珠子排列在一条竖直直线上,如果能,求出每个珠子距离最高的珠子的距离,珠子的位置可重叠。

【分析】

        可以根据珠子的位置关系建立一张有向图,A->B 为A比B高,权值为之间的距离。可以发现必须满足下列三种情况:

               1、图有连通;无法比较出不同连通分支的上下关系。

               2、有向图没有环;根据位置的传递关系,不可能自己比自己低。
               3、如果从A到B有多条路径,路径的长度都应该一样;要不然B的位置关系就会有二义性。

       我本来的想法是按顺序验证上面三条规则,把有向图转为无向图判联通,用拓扑排序判环,用DFS来判路径长度,想想太复杂了。后来想想其实没必要那么复杂。对于每条有向边,添加一条负权反向边,任意选定一个点,假设它是最高点,离最高点的距离是0,用DFS搜索可连向的点,如果新点未访问,则新点的距离就是当前点的距离加上边的权值,如果新点被访问过,这需要验证当前点的距离加上边权是否与新点原来的权值相等,如果不相等,则说明有冲突。如果DFS结束还有点没被访问,则说明图不连通。如果发现有点的距离为负数,则说明那个点比搜索开始的点的距离更高。

    DFS的代码很简单:

1 #include 
2 #include
3 struct node 4 { 5 int x,y,c,next; 6 void mset(int a,int b,int z,int nn) 7 { 8 x=a; 9 y=b;c=z;10 next=nn;11 }12 }ev[5000];13 int ej,n,p;14 int map[502];15 int vv[502][502];16 int num[502];17 int dis[502];18 bool ans;19 int mmin;20 int min(int a,int b){
return a
View Code

 另外还可以使用并查集的方法,A是B的双亲就表示A的位置比B的高,对于每个节点保存当前到双亲节点的距离(为正值),这样在并查集的树中,根节点与一个孩子的孩子的孩子.....的孩子的距离就可以在路径压缩的过程中计算出来:

int find(int x){    if (mset[x]==-1) return x;    int t=mset[x];    d[x]+=d[t];  //递推出与根节点的距离    return mset[x]=find(t);}

对于两个不同集合的合并,由于在找集合的过程中使用了find函数,所以相关节点一定直接和集合树的根节点连接。设现在要连接的节点是a、b,它们的根节点分别是roota和rootb, a与b的距离为c, a在b的上面。集合的合并是集合根节点之间的连接,所以需要计算出根节点之间的距离P,b到roota的距离应为d[a]+c, b到rootb的距离为d[b] ,假设rootb成为roota的孩子,着P+d[b]=d[a]+c => P=d[a]+c-d[b].若P为负,则roota应成为roota的孩子,距离为P的绝对值。

1 #include 
2 #include
3 int mset[500]; 4 int d[500],n,p; 5 int find(int x) 6 { 7 if (mset[x]==-1) return x; 8 int t=mset[x]; 9 d[x]+=d[t];10 return mset[x]=find(t);11 }12 13 int main()14 {15 while (~scanf("%d%d",&n,&p))16 {17 memset(mset,-1,sizeof mset);18 memset(d,0,sizeof d);19 bool ans=true;20 for (int i=0;i

=0)30 {31 mset[yy]=xx;d[yy]=p;32 } else33 {34 mset[xx]=yy;d[xx]=-p;35 }36 } else37 {38 if (d[a]+c!=d[b]) ans=false;39 }40 }41 for (int i=1;i<=n;++i) find(i);42 if (ans)43 for (int i=1;i<=n;++i) printf("%d\n",d[i]);44 else printf("-1\n");45 }46 }

View Code

这里能用并查集是利用了孩子和双亲关系的可传递性。

转载于:https://www.cnblogs.com/wuminye/p/3182467.html

你可能感兴趣的文章
NSAttributedString
查看>>
Java复习之网络编程
查看>>
内存管理
查看>>
Python sys模块参考手册
查看>>
Storm的ack机制在项目应用中的坑
查看>>
C#与vb6 com组件的互相调用方法
查看>>
对象-关系映射ORM(Object Relational Mapping)(转)
查看>>
Python入门系列——第14篇
查看>>
ReflectedSchemas应该定期清理否则会占用大量C盘空间
查看>>
Django中的cookie与session
查看>>
JavaScript快速入门(三)——JavaScript语句
查看>>
数据结构与算法历程
查看>>
POJ 1797 Heavy Transportation
查看>>
汇编语言---内存变量的地址
查看>>
ISP DSP的不同
查看>>
深入Linux grep指令的详解(实用型)
查看>>
嵌入式根文件系统的移植和制作详解
查看>>
单片机定时器中断原理
查看>>
Ignite 配置更新Oracle JDBC Drive
查看>>
partproble在RHEL 6下无法更新分区信息
查看>>