【图论】CF685E Travelling Through the Snow Queen's Kingdom

我们可以发现 s>t 这条路径所经过的边的编号单增(且每条边的边号都是大于等于 l),假如不单增那么分界点后的边都不通。

那么,题目中的走一条边花费 1 就是废的

对于一个询问,我们只需要把编号大于等于 l 的拉出去跑最短路即可。

考虑在线过不去,有点 图函数 的意思。

离线询问,从大编号到小编号加入边,询问按 l 降序排。

考虑加入这条边对最短路的影响。

首先,这条边所经过的时间一定是当前全局最小的。那么一定是 fromtoitofromj的形式(根据单增结论),考虑类 floyd 松弛即可。

需要注意的是,松弛的起点都必须是 from or to,能保证一定经过 fromto

途中绿色和蓝色即为路径,保证一定经过新边。

#include <bits/stdc++.h> using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } void pr(int x) { int f=1,tot=0; static int st[30]; if(x<0) x=-x,f=-1; while(x) st[++tot]=x%10,x/=10; if(!tot) putchar('0'); else for(int i=tot;i>=1;i--) putchar(st[i]+'0'); } #define N 1005 #define M (int)(2e5+5) struct edge { int l,r,s,t,id; }Q[M]; bool ans[M]; int fr[M],to[M]; int n,m,q,f[N][N]; bool cmp(edge x,edge y) { return x.l>y.l; } int main() { n=rd(); m=rd(); q=rd(); for(int i=1;i<=m;i++) fr[i]=rd(),to[i]=rd(); for(int i=1;i<=q;i++) { Q[i].l=rd(); Q[i].r=rd(); Q[i].s=rd(); Q[i].t=rd(); Q[i].id=i; } sort(Q+1,Q+1+q,cmp); int nw=1; memset(f,0x3f,sizeof(f)); for(int i=m;i>=1;i--) { f[fr[i]][to[i]]=f[to[i]][fr[i]]=i; for(int j=1;j<=n;j++) { f[to[i]][j]=min(f[to[i]][j],f[fr[i]][j]); f[fr[i]][j]=min(f[fr[i]][j],f[to[i]][j]); } while(nw<=q&&Q[nw].l==i) { if(f[Q[nw].s][Q[nw].t]<=Q[nw].r) ans[Q[nw].id]=1; ++nw; } } for(int i=1;i<=q;i++) { if(ans[i]) printf("Yes\n"); else printf("No\n"); } return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872305.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示