题意描述

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. GAN生成的评价指标 Evaluation of GAN

    传统方法中,如何衡量一个generator ?-- 用 generator 产生数据的 likelihood,越大越好. 但是 GAN 中的 generator 是隐式建模,所以只能从 P_G 中采样 ...

  2. 067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数

    067 01 Android 零基础入门 01 Java基础语法 08 Java方法 05 数组作为方法参数 本文知识点:数组作为方法参数 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...

  3. 《C++primerplus》第7章练习题

    1.用户不断输入两个数,计算调和平均数,直到其中一个数为0. #include<iostream> using namespace std; double harm_mean(double ...

  4. WebStrom配置TypeScript开发环境

    安装NodeJS node.js下载地址:https://nodejs.org/en/download/ 安装TypeScript npm install typescripot -g 新建tscon ...

  5. minikube dashboard报503的错误

    minikube start之后,minikube dashboard启动web界面报503错误 解决方案,删除掉c盘用户目录下的.kube和.minikube目录,重新启动,具体什么原因导致的呢,也 ...

  6. DockerFile系统的学习

    1.背景 DockerFile定义:用来构建Docker镜像的文件,有脚本命令组成. 自定义镜像并运行步骤:编写dockerFile文件-->docker build为镜像-->docke ...

  7. go 正则 爬取邮箱代码

    package main import ( "net/http" "fmt" "io/ioutil" "regexp" ...

  8. selenium--基础学习

    from selenium import webdriver from selenium.common.exceptions import TimeoutException, NoSuchElemen ...

  9. SOAP调用Web Service

    SOAP调用Web Service (示例位置:光盘\code\ch07\ WebAppClient\ JsService4.htm) <html xmlns="http://www. ...

  10. 第一章 数据库管理员(DBA)

    一.DBA的工作 1.初级:mysql基础安装.搭建 2.中级:数据库管理员DBA 1)用户管理 1.用户的权限2.用户可以操作的库或者表3.用户名和来源的主机4.用户的密码​grant all on ...