Connecting...

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 
posted @ 2025-07-20 09:00  余亦宸  阅读(16)  评论(0)    收藏  举报