题解:P11564 【MX-X7-T5】[LSOT-3] 你的列车是生存战略
RaizCuadrada · · 题解
这道题不放图片有点太难以理解了(至少对于我来说)。
思路
首先,
有一个 Trick,每次反转编号二进制的一位,然后建图,这道题就用上了。
然后看到或运算和与运算,以及
或运算:
将每一个
以便于处理边权,我们设
然后建三条单向边
不懂的看图:
左右两侧的点为
与运算
与或运算的区别是,如果是
并变成
图也是如此,并将这两种运算放在同一个图里就行了,最短路会自动选择更优的路径。
时间复杂度
代码
代码使用 AI 润色。
代码中的内容如有不懂的,可以根据上面的图一起看。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=4e18;
const int MAXN=1070000, MAXE=6100000;
int n,m,k,M,tot;
int head[MAXN],to[MAXE],nxt[MAXE],c[MAXN],d[MAXN];
ll ew[MAXE],dis[MAXN],A[16385],B[16385];
inline void add(int u,int v,ll w){
to[++tot]=v;ew[tot]=w;nxt[tot]=head[u];head[u]=tot;
}
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline ll readll(){
ll x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline int ina(int s){return n+1+s;}
inline int outa(int s){return n+M+1+s;}
inline int inb(int s){return n+2*M+1+s;}
inline int outb(int s){return n+3*M+1+s;}
int main(){
n=read();m=read();k=read();M=1<<k;
for(int i=1;i<=n;i++) c[i]=read();
for(int i=1;i<=n;i++) d[i]=read();
for(int s=0;s<M;s++) A[s]=readll();
for(int s=0;s<M;s++) B[s]=readll();
for(int i=1;i<=n;i++){
add(i,ina(c[i]),0);
add(outa(c[i]),i,0);
add(i,inb(d[i]),0);
add(outb(d[i]),i,0);
}
for(int s=0;s<M;s++){
add(ina(s),outa(s),A[s]);
add(inb(s),outb(s),B[s]);
for(int p=0;p<k;p++){
int b=1<<p;
if(!(s&b)){
add(ina(s),ina(s|b),0);
add(outb(s),outb(s|b),0);
}else{
add(outa(s),outa(s^b),0);
add(inb(s),inb(s^b),0);
}
}
}
for(int i=1;i<=m;i++){
int u=read(),v=read();
add(u,v,readll());
}
int N=n+4*M;
for(int i=1;i<=N;i++) dis[i]=INF;
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> q;
dis[1]=0;q.push(make_pair(0,1));
while(!q.empty()){
pair<ll,int> cur=q.top();q.pop();
ll du=cur.first;int u=cur.second;
if(du!=dis[u]) continue;
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
if(dis[v]>du+ew[e]){
dis[v]=du+ew[e];
q.push(make_pair(dis[v],v));
}
}
}
for(int i=1;i<=n;i++) printf("%lld ",dis[i]);
return 0;
}