题解:P13856 [CERC 2023] Labelled Paths
masterhuang · · 题解
板子题,喵了。
这题可以加强为 任意两点求最短路,是等价的。
首先你需要发现一个事实:
但是!
其中
A,B,C 是字符串,+ 是顺序拼接,< 是字典序比较。
所以这题你 必须倒着做 求最短路,此时字典序才是最小的。
建反图,接下来你要对 每个原来的终点,在反图上走拓扑序,进行
比较若干个串拼接在一起的大小,相当于求两个拼接串的 LCP。
显然可以对每一段单独考虑。
就是
显然先求
总共最多比较
比较一组相当于求后缀 LCP,和最后和两个长度取
于是假设求一次两个后缀的 LCP 的复杂度为
使用 SA+RMQ 做到
我写了 SA,总复杂度
- 注意这题边权有空串,比较恶心。
::::info[
#include<bits/stdc++.h>
#define LL long long
#define vec vector<pair<int,int>>
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=1e6+5,M=605;
int n,m,L,S,a[N],pre[M];bool v[M];
vec f[M];basic_string<int>p;
vector<pair<int,pair<int,int>>>E[M];
string C;
int sa[N],rk[N],ht[N],mn[21][N];
inline int lcp(int x,int y)
{
if(x==y) return L-x+1;x=rk[x],y=rk[y];
if(x>y) swap(x,y);int t=__lg(y-(x++));
return min(mn[t][x],mn[t][y-(1<<t)+1]);
}
inline void SA()
{
static int _[N],c[N];int n=L,V=26;
for(int i=1;i<=n;i++) c[a[i]=rk[i]=C[i-1]-'a'+1]++,sa[i]=i;
for(int i=1;i<=V;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[i]]--]=i;
for(int w=1,t=0;w<n;w<<=1,V=t,t=0)
{
for(int i=n-w+1;i<=n;i++) _[++t]=i;
for(int i=1;i<=n;i++) if(sa[i]>w) _[++t]=sa[i]-w;
fill(c+1,c+1+V,0);
for(int i=1;i<=n;i++) c[rk[i]]++;
for(int i=1;i<=V;i++) c[i]+=c[i-1];
for(int i=n;i;i--) sa[c[rk[_[i]]]--]=_[i];
memcpy(_,rk,(n+1)<<2);t=0;
auto eq=[&](int x,int y){return _[x]==_[y]&&_[x+w]==_[y+w];};
for(int i=1;i<=n;i++) rk[sa[i]]=eq(sa[i-1],sa[i])?t:++t;
if(t==n) break;
}
for(int i=1,k=0;i<=n;i++)
{
if(k) k--;
while(a[i+k]==a[sa[rk[i]-1]+k]) k++;
ht[rk[i]]=k;
}memcpy(mn[0],ht,(n+1)<<2);
for(int i=1;(1<<i)<=n;i++) for(int j=1;j+(1<<i)-1<=n;j++)
mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<i-1)]);
}
inline bool cmp(vec A,vec B)// A<B?
{
while(1)
{
while(A.size()&&!A.back().second) A.pop_back();
if(!A.size()) break;
while(B.size()&&!B.back().second) B.pop_back();
if(!B.size()) break;
auto &[x,c]=A.back();auto &[y,d]=B.back();
int L=min({lcp(x,y),c,d});
x+=L,y+=L,c-=L,d-=L;
if(c&&d) return a[x]<a[y];
}
return B.empty()?0:A.empty();
}
void dfs(int x){
v[x]=1;
for(auto [u,_]:E[x]) if(!v[u]) dfs(u);p+=x;
}
int main()
{
cin.tie(0)->sync_with_stdio(0);cout.tie(0);cin>>n>>m>>L>>S>>C;SA();
for(int u,v,l,d;m--;) cin>>u>>v>>l>>d,E[v].push_back({u,{l,d}});
for(int u=1;u<=n;u++)
{
if(u==S){cout<<"1 "<<S<<"\n";continue;}
for(int i=1;i<=n;i++) f[i].clear(),pre[i]=0;
p.clear();fill_n(v+1,n,0);
dfs(u);reverse(p.begin(),p.end());
for(int i:p)
{
for(auto [j,w]:E[i])
{
vec t=f[i];t.push_back(w);
if(f[j].empty()||cmp(t,f[j])) swap(f[j],t),pre[j]=i;
}
}
if(!f[S].size()){cout<<"0\n";continue;}
basic_string<int>g;for(int i=S;i;i=pre[i]) g+=i;
cout<<g.size()<<" ";for(int i:g) cout<<i<<" ";cout<<"\n";
}
return 0;
}
::::