题解 P4366 【[Code+#4]最短路】
Problem
想要数据的可以去Code+上下载
题意:
给定
Solution
明显不能直接
但这样的最坏复杂度依旧是跑不过的(code+上这题的测试点有99个,骗分基本骗不满)
本着在任意一个正解中绝对不可能处理所有的
比如:
3 xor 6 = 5 \Leftrightarrow 11_2 xor 110_2 = 101_2 5 二进制下有之间有两个 1 那么这个值可以由100_2 和1_2 这两个值合并而得 即边(3,6)=(3,7)+(7,6) 其权值对应为101_2$ $100_2$ $1_2
则对于任意点
则问题简化到只有
注意
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>0?(x):(-(x)))
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=201000,M=1001000,inf=2147483647;
struct Edge{int v,w,nxt;}a[M];
int head[N],dis[N],seg[N<<2];
char bo[N];
int n,m,c,_,ds,s,t;
inline void add(int u,int v,int w){a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;}
#define mid (((l)+(r))>>1)
inline void build(int l,int r,int x){
if(l==r){seg[x]=inf;return ;}
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
seg[x]=inf;
if(~seg[x<<1])seg[x]=min(seg[x],seg[x<<1]);
if(~seg[x<<1|1])seg[x]=min(seg[x],seg[x<<1|1]);
return ;
}
inline void update(int l,int r,int x,int pos,int t){
if(l==r){seg[x]=min(seg[x],t);return ;}
if(pos<=mid)update(l,mid,x<<1,pos,t);
else update(mid+1,r,x<<1|1,pos,t);
seg[x]=inf;
if(~seg[x<<1])seg[x]=min(seg[x],seg[x<<1]);
if(~seg[x<<1|1])seg[x]=min(seg[x],seg[x<<1|1]);
return ;
}
inline int query(int l,int r,int x){
if(l==r){ds=seg[x];return l;}
if(seg[x]==seg[x<<1])return query(l,mid,x<<1);
else if(seg[x]==seg[x<<1|1])return query(mid+1,r,x<<1|1);
else return -1;
}
#undef mid
void spath(){
build(0,n,1);
update(0,n,1,s,0);
while(!bo[t]){
rg int x=query(0,n,1);
bo[x]=1;dis[x]=ds;
update(0,n,1,x,-1);
for(rg int i=head[x];i;i=a[i].nxt)
if(!bo[a[i].v])update(0,n,1,a[i].v,dis[x]+a[i].w);
for(rg int i=1;i<=n;i<<=1)
if(!bo[x^i]&&(x^i)<=n)update(0,n,1,x^i,dis[x]+c*i);
}
return ;
}
int main(){
read(n);read(m);read(c);
for(rg int i=0,x,y,z;i<m;++i)read(x),read(y),read(z),add(x,y,z);
read(s);read(t);
spath();
printf("%d\n",dis[t]);
return 0;
}