P9361 [ICPC 2022 Xi'an R] Contests
P9361 [ICPC 2022 Xi'an R] Contests - 洛谷
思路
想了个暴力写法:\(O(n^2)\) 建边,跑最短路。
正解:倍增。这题貌似可以开阔倍增的思路,即不止在一条链上跳,可以跳来跳去。
观察性质:某个点跳的某一条链的下一个点,若该点排名最小(最高),一定不劣(贪心),即只需维护每条连的链头。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,inf=1e5;
int n,m,a[6][N],b[6][N];
int f[6][6][21][N]/*fijlk 从i场k位开始跳,跳(1<<l)步,最高排名可以跳到j的f位*/;
int np[6],p[6];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1;i<=m;++i)for(int j=1;j<=m;++j)for(int l=0;l<=20;++l)for(int k=1;k<=n;++k)f[i][j][l][k]=inf;
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j){
cin>>a[i][j];
b[i][a[i][j]]=j;
}
}
//init f[i][j][0][k]
for(int i=1;i<=m;++i){
for(int j=1;j<=m;++j){
int rk=n+1;
for(int k=n;k>=1;--k){
int p=a[i][k];
rk=min(rk,b[j][p]);
f[i][j][0][k]=rk;
}
}
}
for(int l=1;l<21;++l){
for(int i=1;i<=m;++i){
for(int j=1;j<=m;++j){
for(int k=1;k<=n;++k){
for(int p=1;p<=m;++p){
f[i][j][l][k]=min(f[i][j][l][k],f[p][j][l-1][f[i][p][l-1][k]]);
}
}
}
}
}
int q;cin>>q;
//只考虑每场比赛可达最小排名
while(q--){
int x,y;
cin>>x>>y;
int flg=0;
for(int i=1;i<=m;++i){
if(b[i][x]<b[i][y])flg=1;
p[i]=b[i][x];
}
if(flg==1){
cout<<1<<"\n";
continue;
}
int ans=0;
for(int l=20;l>=0;--l){
for(int k=1;k<=m;++k) np[k]=(int)1e9;
for(int i=1;i<=m;++i){
for(int k=1;k<=m;++k) np[k]=min(np[k],f[i][k][l][p[i]]);
}
int flg=0;
for(int k=1;k<=m;++k) flg|=(np[k]<b[k][y]);
if(!flg){
ans+=(1ll<<l);
for(int k=1;k<=m;++k)p[k]=np[k];
}
}
if(ans<=n)cout<<ans+2<<"\n";
else cout<<"-1\n";
}
return 0;
}
写挂了的暴力,貌似 RE 了。路过者看看一眼呗。
#include<bits/stdc++.h>
using namespace std;
const int N1=5050,N=1e5+10,inf=1e5+10;
#define fi first
#define se second
#define pii pair<int,int>
int n,m,rk[10][N],name[N];
int bj[N1][N1],dis[N1][N1];
vector<pii>ask[N1];
int ans[N1];
priority_queue<int>q;
int vis[N],mndis[N];
void dijk(int s){
for(int i=1;i<=n;++i)mndis[i]=inf,vis[i]=0;
mndis[s]=0;
vis[s]=1;
q.push(s);
while(q.size()){
int f=q.top();q.pop();
vis[f]=0;
for(int i=1;i<=n;++i){
if(i==f)continue;
if(mndis[i]>mndis[f]+dis[f][i]){
mndis[i]=mndis[f]+dis[f][i];
if(!vis[i])q.push(i),vis[i]=1;
}
}
}
for(auto v:ask[s]){
ans[v.se]=mndis[v.fi];
}
}
int main(){
// freopen("orz1.in","r",stdin);
// freopen("orz.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j)
cin>>rk[i][j];
for(int j=1;j<=n;++j){
for(int k=j+1;k<=n;++k){
bj[rk[i][j]][rk[i][k]]=1;
}
}
}
if(m==1){
int q;
cin>>q;
while(q--){
int x,y;
cin>>x>>y;
for(int i=1;i<=n;++i)name[rk[1][i]]=i;
if(name[x]>name[y])cout<<-1<<"\n";
else cout<<1<<"\n";
}
return 0;
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(i==j)continue;
dis[i][j]=inf;
if(bj[i][j])dis[i][j]=1;
}
}
int q;
cin>>q;
if(n<=520&&q<=520){
for(int k=1;k<=n;++k){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(bj[i][k]&&bj[j][k])dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
while(q--){
int x,y;
cin>>x>>y;
cout<<(dis[x][y]==inf?-1:dis[x][y])<<"\n";
}
return 0;
}
for(int i=1;i<=q;++i){
int x,y;
cin>>x>>y;
ask[x].push_back({y,i});
}
for(int i=1;i<=n;++i){
if(ask[i].size()){
dijk(i);
}
}
for(int i=1;i<=q;++i)cout<<(ans[i]==inf?-1:ans[i])<<"\n";
return 0;
}
//25pts

浙公网安备 33010602011771号