【题目大意】

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

【分析】

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

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

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

DFS的代码很简单:

 #include <stdio.h>
#include <string.h>
struct node
{
int x,y,c,next;
void mset(int a,int b,int z,int nn)
{
x=a;
y=b;c=z;
next=nn;
}
}ev[];
int ej,n,p;
int map[];
int vv[][];
int num[];
int dis[];
bool ans;
int mmin;
int min(int a,int b){return a<b?a:b;}
void insert(int x,int y,int v)
{
int tem=map[x];
ev[ej++].mset(x,y,v,tem);
map[x]=ej-;
vv[x][y]=v;
vv[y][x]=-v;
}
void dfs(int x)
{
if (num[x]) return;
num[x]=;
int p=map[x];
while (p!=- && ans)
{
node tt=ev[p];
int t2=dis[x]+tt.c;
if (dis[tt.y]!=- && dis[tt.y]!=t2)
{
ans=false;
return;
}
dis[tt.y]=t2;
dfs(tt.y);
p=tt.next;
}
}
int main()
{
ej=;mmin=;
ans=true;
//freopen("in.txt","r",stdin);
memset(map,-,sizeof map);
memset(num,,sizeof num);
memset(dis,-,sizeof dis);
scanf("%d%d",&n,&p);
for (int i=;i<p;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
insert(a,b,c);
insert(b,a,-c);
num[b]=;
}
int p=;
for (int i=;i<=n;++i)
if (num[i]==) {p=i;break;}
memset(num,,sizeof num);
if (p==)
{
printf("-1\n");
return ;
}
//printf("%d\n",p);
dis[p]=;
dfs(p);
if (!ans)
{
printf("-1\n");
} else
{
for (int i=;i<=n;++i) mmin=min(mmin,dis[i]);
for (int i=;i<=n;++i) printf("%d\n",dis[i]-mmin);
} }

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

int find(int x)
{
if (mset[x]==-) 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的绝对值。

 #include <stdio.h>
#include <string.h>
int mset[];
int d[],n,p;
int find(int x)
{
if (mset[x]==-) return x;
int t=mset[x];
d[x]+=d[t];
return mset[x]=find(t);
} int main()
{
while (~scanf("%d%d",&n,&p))
{
memset(mset,-,sizeof mset);
memset(d,,sizeof d);
bool ans=true;
for (int i=;i<p && ans;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int xx=find(a);
int yy=find(b);
int p=d[a]+c-d[b];
if (xx!=yy)
{
if (p>=)
{
mset[yy]=xx;d[yy]=p;
} else
{
mset[xx]=yy;d[xx]=-p;
}
} else
{
if (d[a]+c!=d[b]) ans=false;
}
}
for (int i=;i<=n;++i) find(i);
if (ans)
for (int i=;i<=n;++i) printf("%d\n",d[i]);
else printf("-1\n");
}
}

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

VIJOS P1540 月亮之眼的更多相关文章

  1. Vijos:P1540月亮之眼

    描述 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝—月亮之眼.吉儿深知“月亮之眼”价值连城:它是由许多珍珠相连而成的,工匠们用金线连接珍珠, ...

  2. 月亮之眼_KEY

    [问题描述] 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝--月亮之眼.吉儿深知"月亮之眼"价值连城:它是由许多珍珠相连 ...

  3. 【CTSC1999】【带权并查集 】月亮之眼

    Description 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝-月亮之眼.吉儿深知"月亮之眼"价值连城:它是由许多 ...

  4. 考前停课集训 Day4 雷

    Day 4 今天Rating掉了两百多 为什么呢 因为是真实力打的 倒数第三 没什么好说的了 这才是我的真实水平 强的人一如既往强 作弊的人一落千丈. 只有我.是的,只有我. 被老师嘲讽了,哎,您真的 ...

  5. 2018-11-1 NOIP 模拟赛解题报告

    T1 Domino 多米诺骨牌 题目大意 给你N个骨牌,上下各有一个数,要使上面一排的和为偶数,同时下面一排的和也为偶数,最多要翻转多少次?如果无法达成那么输出-1. 解法 水题秒切 根据数的奇偶性质 ...

  6. Day4-T3

    原题目 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散 落民间几百年的珍宝——月亮之眼.吉儿深知“月亮之眼”价值连城:它是由许多珍珠相连而成的,工 匠们用金线连 ...

  7. vijos- P1385盗窃-月之眼 (水题 + python)

    P1385盗窃-月之眼 Accepted 标签:怪盗基德 VS OIBH[显示标签] 背景 怪盗基德 VS OIBH 第三话 描写叙述 怪盗基德第三次来到熟悉的OIBH总部.屡屡失败的OIBH这次看守 ...

  8. 【BZOJ 1061】【Vijos 1825】【NOI 2008】志愿者招募

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061 https://vijos.org/p/1825 直接上姜爷论文... #include< ...

  9. canvas流星月亮星星银河

    这是页面的特效,首先月亮直接出现,然后星星和银河渐渐的出现(一闪一闪),最后流星划过,留下完美的句点. 所有的动画都是通过帧来实现的. 星星的代码分为2部分,首先是随机生成星星,然后是绘制星星,最后是 ...

随机推荐

  1. 新版本ffmpeg解码非完整H264帧失败

    按照ffmpeg/doc/examples/decoding_encoding.c中video_decode_example解码H264,新版本ffmpeg解码非完整H264帧,定量读取数据直接给av ...

  2. Apache Spark Streaming的适用场景

    使用场景: Spark Streaming 适合需要历史数据和实时数据结合进行分析的应用场景,对于实时性要求不是特别高的场景也能够胜任.

  3. [iOS UI进阶 - 3.2] 手势识别器UIGestureRecognizer

    A.系统提供的手势识别器   1.敲击手势 UITapGestureRecognizer numberOfTapsRequired: 敲击次数 numberOfTouchesRequired: 同时敲 ...

  4. Session.Abandon, Session.Clear和Session.Remove的区别

    Session.Clear()就是把Session对象中的所有项目都删除了, Session对象里面啥都没有.但是Session对象还保留. Session.Abandon()就是把当前Session ...

  5. POJ 2528 Mayor's posters (线段树区间更新+离散化)

    题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...

  6. Light oj 1197 - Help Hanzo (素数筛技巧)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1197 给你a和b求a到b之间的素数个数. 先在小区间素数筛,大区间就用类似素数筛的想法 ...

  7. Spring Data JPA Tutorial Part Nine: Conclusions(未翻译)

    This is the ninth and the last part of my Spring Data JPA tutorial. Now it is time to take a look of ...

  8. [转]Oracle关于null的处理

    转至:http://www.2cto.com/database/201209/157606.html 关于空值null的排序问题   Oracle排序中NULL值处理的五种常用方法:    1.缺省O ...

  9. Java学习笔记(一):数据类型与变量

    数据类型 Java中存在2种数据类型,下面我们来详解一下: 基本数据类型: 引用数据类型: 可以用一张表来记录: 基本数据类型 整型 byte:1个字节8位,取值范围为:[-128, 127],直接写 ...

  10. SOS 调试扩展 (SOS.dll)

    http://blog.csdn.net/cslie/article/details/2158780 SOS 调试扩展 (SOS.dll) 提供公共语言运行时(CLR)内部环境的有关信息,帮助你在Wi ...