题意描述

Around the world

在一个圆上有 \(n\) 点,其中有 \(m\) 条双向边连接它们,每条双向边连接两点总是沿着圆的最小弧连接。

求从 \(1\) 号点出发并回到 \(1\) 号点的一条路径,在满足并非原路返回的情况下满足经过路线数量最小。

如果不存在这样的路径输出 \(-1\)。

算法分析

本来好好的一道 BFS 被我想的辣么复杂...。

如果是单向边就是一遍 BFS 的事,但是这里是双向边又不能原路返回...。

首先考虑特殊建边:

对于 \(edge(u,v)\),求出两者的距离 \(w=dis(u,v)\)。

如果 \(u\to v\) 是顺时针走建立 \(edge(u,v,w),edge(v,u,-w)\)。

否则建立 \(edge(v,u,w),edge(u,v,-w)\)。

然后 BFS 的同时计算走过的边权之和,只要到达 \(1\) 号点时边权之和 \(\neq 0\) 即可。

判重本来是用 \(bool\) 判的,然后喜得 MLE,所以乖乖用 set 了。

当然为了减小常数,dalao 都是直接用 Hash。(蒟蒻我懒...)

没了。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#define N 5010
#define M 25010
using namespace std; int n,m,a[N],head[N],cnt=0;
struct Edge{
int nxt,to,val;
}ed[M<<1];
struct node{
int u,dis,step;
};
queue<node>q;
set<pair<int,int> >s; int read(){
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
} int get_dis(int u,int v){
int w=min(abs(u-v),360-abs(u-v));
if((u+w)%360==v) return w;
return -w;
} void add(int u,int v,int w){
ed[++cnt]=(Edge){head[u],v,w},head[u]=cnt;
ed[++cnt]=(Edge){head[v],u,-w},head[v]=cnt;
return;
} int bfs(){
q.push((node){1,0,0});
while(!q.empty()){
node now=q.front();q.pop();
int u=now.u,dis=now.dis,step=now.step;
s.insert(make_pair(u,dis));
for(int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to,w=ed[i].val;
if(v==1 && dis+w) return step+1;
if(s.find(make_pair(v,dis+w))!=s.end()) continue;
//set 提供 find 这个成员函数,如果其中没有这个值将返回 s.end()。
q.push((node){v,dis+w,step+1});
}
}
return -1;
} int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=m;i++){//特殊建边。
int u=read(),v=read();
int w=get_dis(a[u],a[v]);
if(w>0) add(u,v,w);
else add(v,u,-w);
}
printf("%d\n",bfs());
return 0;
}

完结撒花

POJ2432 Around the world的更多相关文章

随机推荐

  1. 梯度下降法Gradient descent(最速下降法Steepest Descent)

    最陡下降法(steepest descent method)又称梯度下降法(英语:Gradient descent)是一个一阶最优化算法. 函数值下降最快的方向是什么?沿负梯度方向  d=−gk

  2. 08 . Jenkins之SpringCloud微服务+Vue+Docker持续集成

    简介 大致流程 /* 1.开发人员每天把代码提交到Gitlab代码仓库 2.jenkins从gitlab中拉取项目源码,编译并打包成war包,然后构建Docker镜像,将镜像上传到Harbor私有仓库 ...

  3. matlab中figure创建图窗窗口

    来源:https://ww2.mathworks.cn/help/matlab/ref/figure.html?searchHighlight=figure&s_tid=doc_srchtit ...

  4. matlab中reshape 重构数组

    来源:https://ww2.mathworks.cn/help/matlab/ref/reshape.html?searchHighlight=reshape&s_tid=doc_srcht ...

  5. .NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记

    目录 什么是软件架构 软件架构的基本思路 单体向分布式演进.云原生.技术中台 1.1 什么是软件架构 1.1.1 什么是架构? Software architecture = {Elements, F ...

  6. shell-变量的数值运算let内置命令

    1. let命令的用法 格式: let 赋值表达式 [注]let赋值表达式功能等同于:((赋值表达式))  范例1:给自变量i加8 [root@1-241 scripts]# i=2 [root@1- ...

  7. devops-jenkins-Pipeline实战

    1) 配置gitlab的分支项目 点击红色标记的创建 project 项目 点击Create project创建Pipeline-demo项目 项目创建完成,然后我们创建一个Add README 然后 ...

  8. JS判断PC操作系统版本

    var version = navigator.userAgent; console.log(version); //"Mozilla/5.0 (Windows NT 10.0; WOW64 ...

  9. volatile、ThreadLocal的使用场景和原理

    并发编程中的三个概念 原子性 一个或多个操作.要么全部执行完成并且执行过程不会被打断,要么不执行.最常见的例子:i++/i--操作.不是原子性操作,如果不做好同步性就容易造成线程安全问题. 可见性 多 ...

  10. 多测师_讲解python__004 函数

    # 函数:一个工具,随调随用# 降级代码冗余## 增加代码的复用性,提高开发效率,为了不成为cv战士## 提高程序扩展性## 函数有两个阶段:定义阶段,调用阶段.## 定义时:只检查函数体内代码语法, ...