分析:
根据异或与加法运算的相似性,可以发现只需连接长度为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;
}