【nowcoder】赛前集训营5
无形的博弈
并不想说话 全都可以 真·无形的博弈
int main(){
#ifndef ONLINE_JUDGE
freopen("T1.txt","r",stdin);
#endif
rd(n);
for(int i=1;i<=n;++i) ans=(ans<<1)%P;
printf("%d",ans);
return 0;
}
十二桥问题
发现桥很少 可以状压
不想调了 92昏
struct node{int x,y,w;}a[30];int b[30];
int tot=0,head[N];
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
ll dis[N],mp[30][30];bool vis[N];
priority_queue<pli>q;
void dij(int s){
memset(vis,0,sizeof(vis)),memset(dis,inf,sizeof(dis));
q.push(make_pair(dis[b[s]]=0ll,b[s]));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u],v;i;i=e[i].nxt)
if(dis[v=e[i].v]>dis[u]+e[i].w) q.push(make_pair(-(dis[v]=dis[u]+1ll*e[i].w),v));
}
for(int i=1;i<=b[0];++i) mp[s][i]=dis[b[i]];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("T2.txt","r",stdin);
#endif
rd(n),rd(m),rd(K);
memset(f,inf,sizeof(f)),b[0]=0;
for(int i=1,u,v,w;i<=m;++i){
rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
if(i<=K) a[i]=(node){u,v,w},b[++b[0]]=u,b[++b[0]]=v;
}
b[++b[0]]=1,sort(b+1,b+b[0]+1);
b[0]=unique(b+1,b+b[0]+1)-b-1;
for(int i=1;i<=K;++i) a[i].x=lower_bound(b+1,b+b[0]+1,a[i].x)-b,a[i].y=lower_bound(b+1,b+b[0]+1,a[i].y)-b;
for(int i=1;i<=b[0];++i) dij(i);
for(int i=1;i<=K;++i)
f[1<<(i-1)][i][0]=mp[1][a[i].y]+a[i].w,f[1<<(i-1)][i][1]=mp[1][a[i].x]+a[i].w;
for(int i=0;i<(1<<K);++i){
for(int j=1;j<=K;++j){
if(!(i&(1<<(j-1)))) continue;
for(int k=1,sta;k<=K;++k)
if(!(i&(1<<(k-1))))
sta=(i|(1<<(k-1))),
f[sta][k][0]=min(f[sta][k][0],f[i][j][0]+mp[a[j].x][a[k].y]+a[k].w),
f[sta][k][0]=min(f[sta][k][0],f[i][j][1]+mp[a[j].y][a[k].y]+a[k].w),
f[sta][k][1]=min(f[sta][k][1],f[i][j][0]+mp[a[j].x][a[k].x]+a[k].w),
f[sta][k][1]=min(f[sta][k][1],f[i][j][1]+mp[a[j].y][a[k].x]+a[k].w);
}
}
for(int i=1;i<=K;++i)
ans=min(ans,min(f[(1<<K)-1][i][0]+mp[a[i].x][1],f[(1<<K)-1][i][1]+mp[a[i].y][1]));
printf("%lld\n",ans);
return 0;
}
神J上树
树链剖分后在重链上面往下跳 剖分时处理出来\(f[u][0]\)是第一个小于\(u\)的点,\(g[u][0]\)为\(u\)到该链上第一个小于\(u\)的距离
然后询问时 先记录\(y\)向上跳时经历的点 然后再由\(x\)向下跳 先倍增跳到第一个小于它的点的后面一个点 然后再往下跳小于它的点
int tot=0,head[N];
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
ll dis[N];
int idx=0,dfn[N],id[N],pos[N],dep[N],fa[N],son[N],top[N],bot[N],sz[N];
void dfs1(int u,int ff){
fa[u]=ff,sz[u]=1,dep[u]=dep[ff]+1;
for(int i=head[u],v,mxs=-1;i;i=e[i].nxt)
if((v=e[i].v)!=ff)
dis[v]=dis[u]+e[i].w,dfs1(v,u),sz[u]+=sz[v],(mxs<sz[v])?(mxs=sz[v],son[u]=v),1:1;
}
stack<int>S;int f[N][21];ll g[N][21];
void dfs2(int u,int topf){
id[dfn[u]=++idx]=u,top[u]=topf;
if(!son[u]){bot[u]=u;return;}
dfs2(son[u],topf),bot[u]=bot[son[u]];
for(int i=head[u],v;i;i=e[i].nxt)
if((v=e[i].v)!=fa[u]&&v!=son[u]) dfs2(v,v);
if(top[u]==u){
int l=dfn[u],r=dfn[bot[u]];
while(!S.empty()) S.pop();
for(int i=r;i>=l;--i){
while(!S.empty()&&S.top()>id[i]) S.pop();
if(!S.empty()) f[id[i]][0]=S.top(),g[id[i]][0]=1ll*id[i]*(dis[f[id[i]][0]]-dis[id[i]]);
S.push(id[i]);
}
}
}
void doubling(){
for(int j=1;j<=20;++j)
for(int i=1;i<=n;++i)
f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[f[i][j-1]][j-1]+g[i][j-1];
}
int tt,fr[N],to[N];
ll qrange(int x,int y){
if(dfn[y]<dfn[x]||dfn[x]+sz[x]-1<dfn[y]) return -1;
tt=0;ll ans=0;
while(top[x]!=top[y]) to[++tt]=y,fr[tt]=top[y],y=fa[top[y]];
fr[++tt]=x,to[tt]=y;
int s,t,nw=x;
while(tt){
s=fr[tt],t=to[tt--];
if(s!=x) ans+=1ll*nw*(dis[s]-dis[fa[s]]);
for(int i=20;i>=0;--i)
if(f[s][i]&&f[s][i]>=nw&&dis[f[s][i]]<=dis[t])
ans+=1ll*nw*(dis[f[s][i]]-dis[s]),s=f[s][i];
if(f[s][0]&&s>=nw&&dis[f[s][0]]<=dis[t]) ans+=1ll*nw*(dis[f[s][0]]-dis[s]),s=f[s][0];
for(int i=20;i>=0;--i)
if(f[s][i]&&dis[f[s][i]]<=dis[t]) ans+=g[s][i],s=f[s][i];
ans+=1ll*(nw=min(s,nw))*(dis[t]-dis[s]);
}
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("T3.txt","r",stdin);
#endif
rd(n),rd(m);
for(int i=1,u,v,w;i<n;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
dfs1(1,0),dfs2(1,1),doubling();
for(int i=1,x,y;i<=m;++i){
rd(x),rd(y);
if(x==y){puts("0");continue;}
else if(dep[x]>=dep[y]){puts("-1");continue;}
else if(x==1){printf("%lld\n",dis[y]);continue;}
else printf("%lld\n",qrange(x,y));
}
return 0;
}