问题描述:
多年来,FJ在世界各地结交了大量的农民朋友。由于他有一段时间没有拜访来自英格兰的“Farmer Ted”和来自荷兰的“Boer Harms”,他很想去拜访他们。
他知道他的每个世界各地的朋友所居住的农场的经度。该经度是描述农场在地球上的位置的角度(0..359 范围内的整数),我们将其视为圆形,而不是更复杂和传统的球形表示。除了明显的不连续性外,在这个圆圈上顺时针行驶时,经度会增加。
FJ 计划乘飞机去拜访他的 N (1 <= N <= 5,000) 个朋友(他们的农场唯一编号为 1..N)。他知道连接不同农场的 M (1 <= M <= 25,000) 个双向航班的时间表。飞机总是在地球表面上以最短的路径飞行(即,在最短的圆弧上)。
两个直接相连的农场之间总会有一条唯一的最短路径。没有一对对映农场(在圆圈上彼此完全相对)直接相连。
每架飞机的飞行都可以被描述为在地球表面沿顺时针或逆时针方向飞行。例如,从经度 30 到经度 35 的航班将是顺时针方向的,从经度 350 到经度 10 的航班也是如此。然而,从经度 350 到经度 200 的航班遵循绕圆逆时针方向的最短路径。
如果 FJ 可以环游世界,顺便拜访一些他的朋友,他会觉得很酷。他想知道这是否可行,如果可行,他可以乘坐的最少航班数量是多少。
他想在他最好的朋友(下面输入中第一个列出的那个)的位置开始和结束他的旅程。为了确保他确实绕地球一圈,他想确保他顺时针行驶的距离与逆时针行驶的距离不同
问题分析:
整体的思路就是用一个二维数组来存每个点的状态包括走过来的距离,但由于状态量过多,所以用哈希算法来搞,bfs出最短路径。
输入 :
第 1 行:两个空格分隔的整数:N 和 M
第 2..N+1 行:第 i+1 行包含一个整数:第 i 个农场的经度。第 2 行包含他最好的朋友的农场的位置。
第 N+2..N+M+1 行:第 i+N+1 行包含两个整数,给出由航班连接的两个农场的索引。
输出:
第 1 行:一个整数,指定 FJ 环游世界需要访问的最少航班数。每次 FJ 从一个农场移动到另一个农场都算作一次飞行。如果不可能进行这样的行程,则输出整数-1。
样本输入:
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
#define N 5001
int a[N];
vector<int> adj[N];
set<int> se[N];//判重 se[i] 标记航班到达i点所旋转的角度有哪些
struct Node
{
int pos,x,cnt;
}que[500000];
int Bfs() //BFS 搜索 关键在于判重
{
Node now,next;
now.pos=1;
now.x=0;
now.cnt=0;
se[1].insert(0);
int front=0,rear=0;
int u,v,tx;
que[rear++]=now;
while(front<rear)
{
now=que[front++];
u=now.pos;
for(int i=0;i<adj[u].size();i++)
{
v=adj[u][i];
tx=a[u]-a[v];
if(tx>180) tx-=360;
if(tx<-180) tx+=360;
tx+=now.x;
if(se[v].find(tx)==se[v].end()) //判重条件
{
if(v==1) return now.cnt+1;
se[v].insert(tx);
next.pos=v;
next.x=tx;
next.cnt=now.cnt+1;
que[rear++]=next;
}
}
}
return -1;
}
int main()
{
int n,m; //n个城市,m条边,给定每个城市的经度,遵循最短原则,然后遍历一周回来,求最少要做多少次航班
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) //横向判重
{
adj[i].clear();
se[i].clear();
scanf("%d",&a[i]);
}
int u,v;
for(int i=0;i<m;i++) //纵向判重
{
scanf("%d%d",&u,&v);
adj[u].push_back(v);
adj[v].push_back(u);
}
printf("%d\n",Bfs());
}
return 0;
}
yjg