P11964 [GESP202503 七级] 图上移动

题目

传送门

思路

参考了洛谷的第一篇题解

简单做法

我们发现只要遍历每个k和每个点即可,然后对每个点和k做dfs,用集合set去重即可

#include<bits/stdc++.h>
using namespace std;
int n,m,k,mb;
set<int>s;
vector<int>v[505]; 
void dfs(int x,int now){
	if(now==mb){
		s.insert(x);
		return;
	}
	for(int i=0;i<v[x].size();i++){
		int u=v[x][i];
		dfs(u,now+1);
	}
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=k;j++){
			s.clear();
			mb=j;
			dfs(i,0);
			cout<<s.size()<<' ';
		}
		cout<<'\n';
	}
	return 0;
} 

但是这种做法会超时,时间复杂度达到了o(nk(n^k)),只能得20分
提交记录

如何优化?

我们可以给每个点都定义一个状态,定义vis[i][j]为走到i点时用了j步。
然后dfs,如果走过就直接返回,否则就遍历与他相邻的边。

代码

有注释

#include<bits/stdc++.h>
using namespace std;
int n,m,k,mb;
int vis[505][25]; 
vector<int>v[505]; 
void dfs(int x,int step){
	if(vis[x][step])return;//走过了 
	vis[x][step]=1;//标记 
	if(step>=k)return;//边界 
	for(int i=0;i<v[x].size();i++){
		int u=v[x][i];
		dfs(u,step+1);
	}
} 
int main(){
	std::ios::sync_with_stdio(false);//关闭输入输出流 
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		dfs(i,0);//dfs 
		for(int j=1;j<=k;j++){
			int ans=0;
			for(int i1=1;i1<=n;i1++){
				ans+=vis[i1][j];//统计 
			}
			cout<<ans<<' ';
		}
		cout<<'\n';
		for(int j=1;j<=k;j++){
			for(int i1=1;i1<=n;i1++){
				vis[i1][j]=0;//初始化 
			}
		}
	}
	return 0;
} 

无注释

#include<bits/stdc++.h>
using namespace std;
int n,m,k,mb;
int vis[505][25]; 
vector<int>v[505]; 
void dfs(int x,int step){
	if(vis[x][step])return;
	vis[x][step]=1;
	if(step>=k)return;
	for(int i=0;i<v[x].size();i++){
		int u=v[x][i];
		dfs(u,step+1);
	}
} 
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		dfs(i,0);
		for(int j=1;j<=k;j++){
			int ans=0;
			for(int i1=1;i1<=n;i1++){
				ans+=vis[i1][j];
			}
			cout<<ans<<' ';
		}
		cout<<'\n';
		for(int j=1;j<=k;j++){
			for(int i1=1;i1<=n;i1++){
				vis[i1][j]=0;
			}
		}
	}
	return 0;
} 

点赞

posted @ 2026-08-30 21:26  陈晨2011  阅读(8)  评论(0)    收藏  举报