炫酷路途

【题目描述】

小希现在要从寝室赶到机房,路途可以按距离分为N段,第i个和i+1个是直接相连的,只需要一秒钟就可以相互到达。

炫酷的是,从第i个到第i+2p个也是直接相连的(其中p为任意非负整数),只需要一秒钟就可以相互到达。

更炫酷的是,有K个传送法阵使得某些u,v之间也是直接相连的,只需要一秒钟就可以相互到达,当然,由于设备故障,可能会有一些u=v的情况发生。

现在小希为了赶路,她需要在最短的时间里从寝室(编号为1)到达机房(编号为N),她不希望到达这N个部分以外的地方(不能到达位置N+1),也不能走到比自己当前位置编号小的地方(比如从5走到3是非法的)。

她想知道最短的时间是多少。

【输入描述】

第一行输入两个整数N,K,表示路途的段数和传送法阵的数量。

从第二行开始K行,每行两个整数ai,bi表示两个位置之间相连。

2≤N≤1,000,000,000
0≤K≤15

【输出描述】

输出一个整数,表示从寝室到机房最短的时间是多少秒。

【样例】

示例1

输入
12 2
1 5
6 6
输出
3

示例2

输入
17 2
2 5
8 9
输出
1

思路:

n 很大很吓人但其实影响不大,实际上将所有额外连边的 k*2 个点再加上起点、终点就可以构成一张图,最多只有 32 个点,然后计算两点间的距离求最短路即可

【源代码】

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PI acos(-1.0)
#define E 1e-6
#define INF 0x3f3f3f3f
#define N 3001
#define LL long long
const int MOD=1e9+7;
using namespace std;
int n,m;
struct Edge{
    int x,y;
}edge[N];
struct Node{
    int x,w;
    Node(){}
    Node(int x,int w):x(x),w(w){}
    bool operator < (const Node &rhs)const{
        return w>rhs.w;
    }
};
vector mp;//图
int G[N][N];//边权
int res[N];
bool vis[N];
int bit(int x){//计算x中1的个数
    int cnt=0;
    while(x){
        if(x&1)
            cnt++;
        x>>=1;
    }
    return cnt;
}
int calculate(int x){//计算图中第一个大于等于x的位置
    return lower_bound(mp.begin(),mp.end(),x)-mp.begin();
}
void dijkstra(){
    memset(res,INF,sizeof(res));
    res[0]=0;

    priority_queue Q;
    Q.push(Node(0,0));

    while(!Q.empty()){
        int x=Q.top().x;
        int w=Q.top().w;
        Q.pop();

        vis[x]=true;
        for(int y=0;y>n>>m;

    int cnt=0;
    for(int i=0;i>x>>y;
        if(x!=y&&x<=n&&y<=n){
            if(x>y)//序号小者在前,保证边是有向的
                swap(x,y);
            //存点
            mp.push_back(x);
            mp.push_back(y);
            //存边
            edge[cnt].x=x;
            edge[cnt].y=y;
            cnt++;
        }
    }

    mp.push_back(1);//起点
    mp.push_back(n);//终点

    sort(mp.begin(),mp.end());
    mp.erase(unique(mp.begin(),mp.end()),mp.end());//去重

    //计算边权
    memset(G,INF,sizeof(G));
    for(int i=0;i

 

你可能感兴趣的:(#,牛客,#,图论——最短路)