VIJOS P1540 月亮之眼
【题目大意】
有多个珠子,给出部分珠子之间的相对上下位置和间距,问你这些珠子在满足给出的条件下,是否能把珠子排列在一条竖直直线上,如果能,求出每个珠子距离最高的珠子的距离,珠子的位置可重叠。
【分析】
可以根据珠子的位置关系建立一张有向图,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 月亮之眼的更多相关文章
- Vijos:P1540月亮之眼
描述 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝—月亮之眼.吉儿深知“月亮之眼”价值连城:它是由许多珍珠相连而成的,工匠们用金线连接珍珠, ...
- 月亮之眼_KEY
[问题描述] 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝--月亮之眼.吉儿深知"月亮之眼"价值连城:它是由许多珍珠相连 ...
- 【CTSC1999】【带权并查集 】月亮之眼
Description 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散落民间几百年的珍宝-月亮之眼.吉儿深知"月亮之眼"价值连城:它是由许多 ...
- 考前停课集训 Day4 雷
Day 4 今天Rating掉了两百多 为什么呢 因为是真实力打的 倒数第三 没什么好说的了 这才是我的真实水平 强的人一如既往强 作弊的人一落千丈. 只有我.是的,只有我. 被老师嘲讽了,哎,您真的 ...
- 2018-11-1 NOIP 模拟赛解题报告
T1 Domino 多米诺骨牌 题目大意 给你N个骨牌,上下各有一个数,要使上面一排的和为偶数,同时下面一排的和也为偶数,最多要翻转多少次?如果无法达成那么输出-1. 解法 水题秒切 根据数的奇偶性质 ...
- Day4-T3
原题目 吉儿是一家古董店的老板娘,由于她经营有道,小店开得红红火火.昨天,吉儿无意之中得到了散 落民间几百年的珍宝——月亮之眼.吉儿深知“月亮之眼”价值连城:它是由许多珍珠相连而成的,工 匠们用金线连 ...
- vijos- P1385盗窃-月之眼 (水题 + python)
P1385盗窃-月之眼 Accepted 标签:怪盗基德 VS OIBH[显示标签] 背景 怪盗基德 VS OIBH 第三话 描写叙述 怪盗基德第三次来到熟悉的OIBH总部.屡屡失败的OIBH这次看守 ...
- 【BZOJ 1061】【Vijos 1825】【NOI 2008】志愿者招募
http://www.lydsy.com/JudgeOnline/problem.php?id=1061 https://vijos.org/p/1825 直接上姜爷论文... #include< ...
- canvas流星月亮星星银河
这是页面的特效,首先月亮直接出现,然后星星和银河渐渐的出现(一闪一闪),最后流星划过,留下完美的句点. 所有的动画都是通过帧来实现的. 星星的代码分为2部分,首先是随机生成星星,然后是绘制星星,最后是 ...
随机推荐
- 成都Uber优步司机奖励政策(3月5日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- homework-08 C++课程课后思考与练习
经过上次晚交作业导致没分以后 我再也不敢晚交作业了 今天就把这次作业先写了 homework Part 1 1. 理解C++变量的作用域和生命周期 a) 用少于10行代码演示你对局部变量的生命周期的理 ...
- homework_01
一. 程序的架构和思路: 这段求解最大子数组之和的程序使用的主要思想是贪心算法,即每一步求出的都是当前的最优解. 首先这道题要分两种情况来讨论: 1)如果当前的输入中所有的数均为负数时,那么最后的解就 ...
- 关闭SELinux的两种方法
1 永久方法 – 需要重启服务器 修改/etc/selinux/config文件中设置SELINUX=disabled ,然后重启服务器. 2 临时方法 – 设置系统参数 使用命令setenforce ...
- [iOS基础控件 - 6.12.2] Modal
A.概念 1.也可以用来切换控制器 2.如ActionSheet 除了push之外,还有另外一种控制器的切换方式,那就是Modal 任何控制器都能通过Modal的形式展示出来 Modal的默认效果 ...
- HTTP协议状态码详解
HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了. 如果是做AJAX,REST,网络爬虫, ...
- wsus客户端/服务器检查更新
wuauclt /detectnow 客户端检查更新 Wuauclt.exe是Windows自动升级管理程序.该进程会不断在线检测更新 wsusutil.exe wsus服务器命令行工具
- uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心
#139. [UER #4]被删除的黑白树 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/139 Descript ...
- C# 手动读写app config 的源码
public class ConfigOperator { public string strFileName; public string configName; public string con ...
- 详解Android Handler的使用-别说你不懂handler
我们进行Android开发时,Handler可以说是使用非常频繁的一个概念,它的用处不言而喻.本文就详细介绍Handler的基本概念和用法. Handler的基本概念 Handler主 ...