题解:P15628 [ICPC 2022 Jakarta R] Game Show
可以将本题中的这个环抽象成一个图,如下图。
然后发现,如果最短路走了同一条边两次及以上,那么路径一定形成了一个环,而且既然走这个环比不走这个环更短,那说明这个环是一个负环,并且由于这张图强连通,所以无论起点和终点如何变动,都可以一直重复走这个负环使这个值无限小,因此先判断否有负环,如果有的话每次询问都输出 flawed 就可以了。
如果没有负环,那么只有正着走(走红色的路)和反着走(走蓝色的路)两种可能,用前缀和处理即可。
我开始考虑用 SPFA 判断负环,但第十四个点会超时。
发现图中只有可能有两种环,一种是绕一个方向转一整圈(如左下图),另一种是先绕一个方向走一段距离,再绕另一个方向走回来(如右下图)。
对于第一种情况,只需要求出所有正方向的边长和和所有反方向的边长和即可。
对于第二种情况,假设是从点
代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int a[N],b[N],vis[N],cnt[N],qzha[N],qzhb[N];
vector<int>v[N],c[N];
int n,T,flag;
signed main(){
cin>>n>>T;
int cnta=0,cntb=0;
for(int i=1;i<=n;i++){
cin>>a[i];
cnta+=a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
if(a[i]+b[i]<0)flag=1;
cntb+=b[i];
}
if(cnta<0||cntb<0)flag=1;
for(int i=1;i<=n;i++){
qzha[i]=qzha[i-1]+a[i];
}
for(int i=n;i>=1;i--){
qzhb[i]=qzhb[i+1]+b[i];
}
while(T--){
int l,r;
cin>>l>>r;
if(flag){
cout<<"flawed"<<endl;
}
else if(l==r){
cout<<0<<endl;
}
else if(l<r){
cout<<min(qzha[r-1]-qzha[l-1],qzhb[r]+qzhb[1]-qzhb[l])<<endl;
}
else{
cout<<min(qzhb[r]-qzhb[l],qzha[r-1]+qzha[n]-qzha[l-1])<<endl;
}
}
}