\(\mathbf{POJ\;2432}\)题解

题意

给出圆上的\(N\)个点,每个点有一个经度(大于\(0\)小于\(360\));再给出\(M\)条双向边,保证边\(x y\)仅会沿圆上较短的弧连接,且不存在边连接圆上相对的两个点的情况。

求一条从点\(1\)出发最后回到点\(1\),且能环绕圆的经过点数最少的路径。

思路

边权为\(1\)的最短路,显然可以想到BFS。但由于还要满足“能环绕圆”这一条件,我们需要加一些限制。

不妨预处理出每条边的连接的两地间的经度差作为边权,顺时针边置正权,逆时针边置负权,并在BFS的状态中加入一维,表示路径权值和。

那么在BFS时,就可以用已走过的路径权值和\(dis\)来判断一条从\(1\)出发再回到\(1\)的路径是否合法了。

不难发现,若\(dis\)不为\(0\),那么一条从\(1\)出发回到\(1\)的路径一定是合法的,反之亦然。

另外,一个状态\(f(x,dis)\)一定不会出现两次,所以用一个集合(STL set)来记录已经出现过的状态,起一般BFS中标记数组的作用。

最后,在计算答案时用一个成员变量\(step\)记录经过了几个点。

使用以上算法即可通过本题。如果想进一步优化,可以把queue改为手写queue,set改为手写Hash。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//include STL queue
#include<queue>
//include STL set
#include<set>
//include STL pair
#include<utility>
#define N 5005
#define M 25005
using namespace std;
struct pos{
int x,dis;
int step;
}tmp,fro;
struct Edge{
int nxt,to,w;
}e[M<<1];
int n,m,tot=1,head[N],a[N];
queue<pos>q;
set<pair<int,int> >cnt;
void addedge(int x,int y,int z)
{
e[++tot]=(Edge){head[x],y,z},head[x]=tot;//顺时针
e[++tot]=(Edge){head[y],x,-z},head[y]=tot;//逆时针
}
int getdis(int x,int y)//返回两地经度差
{
int z=min(abs(x-y),360-abs(x-y));
if((x+z)%360==y)
return z;//顺时针
else
return -z;//逆时针
}
int bfs()
{
fro.x=1;fro.dis=0,fro.step=0;
q.push(fro);
while(!q.empty())
{
fro=q.front(),q.pop();
int x=fro.x,dis=fro.dis,step=fro.step;
cnt.insert(make_pair(x,dis));
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==1 && dis+e[i].w)
return step+1;
if(cnt.find(make_pair(y,dis+e[i].w))!=cnt.end())
continue;
tmp.x=y,tmp.dis=dis+e[i].w,tmp.step=step+1;
q.push(tmp);
}
}
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
for(int i=1,x,y,z;i<=m;i++){
scanf("%d%d",&x,&y);
z=getdis(a[x],a[y]);
if(z>0) addedge(x,y,z);//顺时针
else addedge(y,x,-z);//逆时针
}
printf("%d\n",bfs());
return 0;
}
/*
3 3
0
120
240
1 2
2 3
1 3
*/

完结撒花

最新文章

  1. js实现数组的排序和分组
  2. IOS自学
  3. 1.ARC和非ARC文件共存
  4. 【codevs1200】 NOIP2012—同余方程
  5. 怎样做出优秀的扁平化设计风格 PPT 或 Keynote 幻灯片演示文稿?(装)
  6. PHP写入Txt
  7. 删除Excel中的打印预览留下的打印线
  8. ubuntu如何安装Mac主题
  9. 洛谷mNOIP模拟赛Day2-入阵曲
  10. Python--抽象类接口类
  11. MySQL中间件之ProxySQL(14):ProxySQL+PXC
  12. PHP文件管理—实现网盘以及压缩包的功能操作
  13. Testing - 软件测试知识梳理 - 软件性能测试
  14. HTTP小幺鸡接口管理工具安装与配置说明
  15. sencha touch调试时Please close other application using ADB: Monitor, DDMS, Eclipse
  16. 【10.14】Bug Bounty Write-up总结
  17. javascript 之数据类型--01
  18. Kafka目录
  19. 【BZOJ4503】两个串 FFT
  20. 20.2 解析与序列化【JavaScript高级程序设计第三版】

热门文章

  1. matlab中floor 朝负无穷大四舍五入
  2. 插头 dp
  3. [C#.NET 拾遗补漏]09:数据标注与数据校验
  4. Codeforces Global Round 11 个人题解(B题)
  5. 笔记本键盘按U键却变成了4
  6. 霍夫曼编码(Huffman)
  7. spring 源码构建
  8. 4-20mA模拟量采集
  9. Jmeter请求元件之参数化CSV
  10. 干货分享:用一百行代码做一个C/C++表白小程序,程序员的浪漫!