[结论题][洛谷P4366][Code+#4]最短路:最短路

分析:

根据异或与加法运算的相似性,可以发现只需连接长度为2的整次幂的边即可。
然后Heap_Dijkstra()搞起。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;

inline LL read(){
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}

const int MAXN=1e5+5;
const int MAXM=5e5+5;
int n,m,s,t;
int ecnt,head[MAXN];
LL c,dis[MAXN];
bool vis[MAXN];

struct Edge{
    int to,nxt;LL w;
}e[MAXM+MAXN*20];

struct Pair{
    int pos;LL dis;
    friend bool operator > (Pair x,Pair y){
        return x.dis>y.dis;
    }
};

inline void add_edge(int bg,int ed,LL val){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].w=val;
    head[bg]=ecnt;
}

priority_queue<Pair,vector<Pair>,greater<Pair> > q;

void Dijkstra(){
    memset(dis,0x3f,sizeof dis);
    while(!q.empty()) q.pop();
    dis[s]=0;
    q.push((Pair){s,0});
    while(!q.empty()){
        int u=q.top().pos;q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int ver=e[i].to;
            if(!vis[ver]&&dis[ver]>dis[u]+e[i].w){
                dis[ver]=dis[u]+e[i].w;
                q.push((Pair){ver,dis[ver]});
            }
        }
    }
}

int main(){
    n=read(),m=read(),c=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read();LL w=read();
        add_edge(u,v,w);
    }
    s=read(),t=read();
    int lim=log2(n)+2;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=lim;j++)
            if((i^(1<<j))<=n) add_edge(i,i^(1<<j),(1<<j)*c);
    Dijkstra();
    printf("%lld\n",dis[t]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9641926.html
今日推荐