【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;
}
posted @ 2019-11-08 11:54  委屈的咸鱼鱼鱼鱼  阅读(108)  评论(0编辑  收藏  举报