joisc 2023 护照
joisc 2023 护照
这题题意好难理解。
题目链接
P9331 [JOISC 2023 Day1] Passport
题意描述
有
解法
最优的的路径一定是先从
这样答案就可以表示为
可以先在反图上对每个点 set
维护没有入队的点求出
我们发现,可以对反图建立一个超级源点,对每个点连接边权为
代码
#include<bits/stdc++.h> using namespace std; const int inf=10000000,N=200010; int n,q; vector<int> L,R; vector<int> node[N<<2]; void add(int u,int l,int r,int L,int R,int v){ if(L<=l&&r<=R){ node[u].emplace_back(v); return; } int mid=(l+r)>>1; if(L<=mid) add(u<<1,l,mid,L,R,v); if(mid<R) add(u<<1|1,mid+1,r,L,R,v); } vector<int> stk; void get(int u,int l,int r,int pos){ stk.insert(stk.end(),node[u].begin(),node[u].end()); node[u].clear(); if(l==r) return ; int mid=(l+r)>>1; if(pos<=mid) get(u<<1,l,mid,pos); else get(u<<1|1,mid+1,r,pos); } int main(){ //freopen("in.in","r",stdin); cin.tie(0),cout.tie(0)->sync_with_stdio(false); cin>>n; L=R=vector<int>(n+1); for(int i=1; i<=n; i++){ cin>>L[i]>>R[i]; } vector<int> d1(n+1),d2(n+1); auto get_dist=[&](int sr,vector<int> &dis)->void{ set<int> st; for(int i=1; i<=n; i++) st.insert(i); dis=vector<int>(n+1,inf); dis[sr]=0; deque<int> Q; Q.push_back(sr); st.erase(sr); while(Q.size()){ int u=Q.front(); Q.pop_front(); auto pnt=st.lower_bound(L[u]); while(pnt!=st.end()&&(*pnt)<=R[u]){ dis[*pnt]=dis[u]+1; Q.push_back(*pnt); auto tmp=next(pnt); st.erase(pnt); pnt=tmp; } } }; // 求原图的 SSSP,在可通过所有数据的解法中未使用 d1=d2=vector<int>(n+1,inf); for(int i=2; i<=n; i++){ add(1,1,n,L[i],R[i],i); } deque<int> Q; d1[1]=0; Q.push_back(1); while(Q.size()){ int u=Q.front(); Q.pop_front(); stk.clear(); get(1,1,n,u); for(auto p:stk){ if(d1[p]!=inf) continue; Q.push_back(p); d1[p]=d1[u]+1; } } for(int i=1; i<=n*4; i++) node[i].clear(); for(int i=1; i<n; i++){ add(1,1,n,L[i],R[i],i); } d2[n]=0; Q.push_back(n); while(Q.size()){ int u=Q.front(); Q.pop_front(); stk.clear(); get(1,1,n,u); for(auto p:stk){ if(d2[p]!=inf) continue; Q.push_back(p); d2[p]=d2[u]+1; } } for(int i=1; i<=n*4; i++) node[i].clear(); vector<int> dis(n+1,inf); priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq; for(int i=2; i<n; i++){ dis[i]=d1[i]+d2[i]-1; pq.push(make_pair(d1[i]+d2[i]-1,i)); } dis[n]=d1[n]; dis[1]=d2[1]; pq.push(make_pair(d1[n],n)); pq.push(make_pair(d2[1],1)); for(int i=1; i<=n; i++){ add(1,1,n,L[i],R[i],i); } while(pq.size()){ auto T=pq.top(); pq.pop(); int u=T.second; stk.clear(); get(1,1,n,u); for(auto p:stk){ if(dis[p]>dis[u]+1){ dis[p]=dis[u]+1; pq.push(make_pair(dis[p],p)); } } } cin>>q; while(q--){ int x; cin>>x; if(dis[x]>n) dis[x]=-1; cout<<dis[x]<<'\n'; } return 0; }
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合终身会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 时隔半年,拾笔分享:来自一个大龄程序员的迷茫自问
· 3 个超火的开源项目「GitHub 热点速览」
· C#-Visual Studio工具使用实践
· [原创]《C#高级GDI+实战:从零开发一个流程图》第02章:画一个矩形,能拖动!
· WineHQ 发布的 Framework Mono 6.14 的这个特性对Windows Form