题解 P8117 【「Wdoi-1.5」旅人 1977】
题解
\textbf{Subtask 1}
容易发现一条边走多次总是不优的。因此可以直接暴力
\textbf{Subtask 2}
用来给选手确认一下题意是否理解正确,因此设置了这个相当于是骗分的点。
\textbf{Subtask 3 \& 4}
开始进入正题。考虑一条边究竟会对最终的结果产生多大的贡献。容易发现,一条边产生的贡献会受到这条边之后的边对
于是可以把所有的边反过来然后
值得注意的是,所有的叶子节点是不会被更新的,因此维护的状态不需要存储最底下这一层,下文把非叶节点称作有效节点。也就是下图当中红色的部分。
首先使用
其中
这张图展现了
小清新
使用分层图,将每个点拆成
总时间复杂度分析:
- 使用
\mathcal O(k) 的复杂度计算出所有有效节点的标号。 - 使用
\mathcal O(f(s)) 的复杂度计算出所有有效状态。 - 使用
\mathcal O(k^3) 暴力预处理出所有可能的(l,r) 对应的A,B,\mathit{num} 。 - 建立分层图跑最短路,复杂度为
\mathcal O(f(s)\cdot m) 。
然而如果你先连边再跑最短路,空间复杂度达到了惊人的
参考代码
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace Hsh{
const int SIZ =3e6-3;
int H[SIZ],N[SIZ],W[SIZ],t; u32 V[SIZ];
void add(int u,u32 v,int w){
V[++t]=v,W[t]=w,N[t]=H[u],H[u]=t;
}
int get(u32 w){
for(int i=H[w%SIZ];i;i=N[i]) if(V[i]==w) return W[i];
return 0;
}
}
namespace IIT{
const int MAXN=16261+3,MAXS=32+3;
int L[MAXS],R[MAXS],P[MAXS],Q[MAXS],F[MAXS],s,g;
u32 A[MAXS][MAXS],B[MAXS][MAXS],N[MAXS][MAXS],C[MAXN];
map<u32,int> M;
int bld(int t,int l,int r){
L[t]=l,R[t]=r; if(l!=r){
int c=l+r>>1;
if(l!=c ) P[t]=bld(++s,l,c ),F[P[t]]=t;
if(r!=c+1) Q[t]=bld(++s,c+1,r),F[Q[t]]=t;
}
return t;
}
int T[MAXS],o;
void clc(int t,int l,int r){
if(l<=L[t]&&R[t]<=r){T[t]=-1,++o;} else {
int c=L[t]+R[t]>>1; T[t]=1;
if(l<=c&&P[t]) clc(P[t],l,r); else if(l<=c) ++o;
if(r> c&&Q[t]) clc(Q[t],l,r); else if(r> c) ++o;
}
}
void dfs(int x,u32 u,int k){
if(x==s+1) {C[++g]=u,Hsh::add(u%Hsh::SIZ,u,g); return;}
if(u&(1u<<F[x])) dfs(x+1,u|1u<<x,k);
dfs(x+1,u,k);
}
void iit(int k){
bld(0,1,k),dfs(1,1,k);
up(1,k,i) up(i,k,j){
memset(T,0,sizeof(T)),clc(0,i,j);
N[i][j]=o,o=0; up(0,s,x){
if(T[F[x]]==-1) T[x]=-1;
if(T[x]==-1) A[i][j]|=1u<<x;
if(T[x]== 1) B[i][j]|=1u<<x;
}
}
}
}
namespace Lst{
const int MAXN =4e6+3,SIZ =2e7+3;
int H[MAXN],V[SIZ],N[SIZ],t;
void add(int u,int v){
V[++t]=v,N[t]=H[u],H[u]=t;
}
}
namespace Gra{
const int MAXN=1000+3,MAXM=3000+3;
const int SIZ =16261+3;
int H[MAXN],V[MAXM],T[MAXM],L[MAXM],R[MAXM],W[MAXM],s,t;
void add(int u,int v,int l,int r,int w){
V[++t]=v,L[t]=l,R[t]=r,W[t]=w,T[t]=H[u],H[u]=t;
}
const int MAXW=65536;
int D[MAXN*SIZ],G[MAXW];
int ppc(u32 u){
return G[u>>16]+G[u&0xFFFF];
}
int dij(int a,int b){
using IIT::g; using IIT::C; using IIT::A;
using IIT::B; using IIT::M; using IIT::N;
up(0,65535,i) G[i]=G[i>>1]+(i&1); Lst::add(1,b*(g+1));
up(1,Lst::MAXN,d) for(int oo=Lst::H[d];oo;oo=Lst::N[oo]){
int o=Lst::V[oo]; if(D[o]&&D[o]<d) continue; D[o]=d;
int u=o/(g+1),x=o%(g+1); if(u==a) return d-1;
for(int i=H[u];i;i=T[i]){
int v=V[i],l=L[i],r=R[i],y=Hsh::get(C[x]|B[l][r]);
int w=W[i]*(ppc(C[x]&A[l][r])+N[l][r]);
int p=v*(g+1)+y;
if(D[p]>d+w||!D[p]) Lst::add(d+w,p),D[p]=d+w;
}
}
return -1;
}
}
namespace Slv{
const int MAXN=1000+3,MAXM=16261+3,MAXK=3000+3;
int U[MAXK],V[MAXK],L[MAXK],R[MAXK],K[MAXK];
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int n,m,k,a,b,t,ans=1e9;
void mian(){
n=qread(),m=qread(),k=qread(),a=qread(),b=qread(); IIT::iit(k);
up(1,m,i){
int u=qread(),v=qread(),l=qread(),r=qread(),w=qread();
Gra::add(v,u,l,r,w);
}
printf("%d\n",Gra::dij(a,b));
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
Slv::mian(); return 0;
}