2 条题解
-
0
本题实际上是求一个点所在连通块内有多少个点,可以用并查集来解决。首先dfs找出一个点所在连通块内所有的点并计算个数,然后把它们合并,并记录下答案。最后对于每一组询问在线回答即可。
时间复杂度为 左右。
#include<bits/stdc++.h> using namespace std; const int N=1005,d[4][2]={1,0,-1,0,0,1,0,-1}; int n,m,dsu[N*N],ans[N*N]; bool c[N][N],vis[N][N]; // 并查集模板 int find(int x){ return dsu[x]==x?x:dsu[x]=find(dsu[x]); } inline void merge(int a,int b){ dsu[find(a)]=find(b); } struct node{ int x,y; }; vector<node> vec; // 用于存储当前连通块内的点 int dfs(int x,int y){ // 深搜找出连通块内的点 vis[x][y]=1; vec.push_back({x,y}); int cnt=1; for(int i=0;i<4;i++){ int xx=x+d[i][0],yy=y+d[i][1]; if(xx>=1&&yy>=1&&xx<=n&&yy<=n&&!vis[xx][yy]&&c[x][y]^c[xx][yy]) cnt+=dfs(xx,yy); } return cnt; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ char p; cin>>p; c[i][j]=p=='1'; dsu[(i-1)*n+j]=(i-1)*n+j; // 并查集初始化 } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(!vis[i][j]){ int cnt=dfs(i,j); for(auto i=vec.begin();i!=vec.end()-1;i++){ node k1=*i,k2=*(i+1); merge((k1.x-1)*n+k1.y,(k2.x-1)*n+k2.y); // 将连通块内所有的点合并 } ans[find((vec[0].x-1)*n+vec[0].y)]=cnt; // 记录答案 vec.clear(); // 清空 } for(int i=1,x,y;i<=m;i++){ scanf("%d%d",&x,&y); printf("%d\n",ans[find((x-1)*n+y)]); // 在线回答 } return 0; }
-
0
#include<bits/stdc++.h> using namespace std; const int N=1001; int n,m,x,y,cnt,d[1001][1001]; int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; char c[N][N]; vector<pair<int,int>>e; void dfs(int x,int y) { d[x][y]=1; cnt+=1; e.push_back({x,y}); for(int i=0;i<=3;i+=1) { int _x=x+dx[i]; int _y=y+dy[i]; if(_x>=1&&_x<=n&&_y>=1&&_y<=n&&c[x][y]!=c[_x][_y]&&d[_x][_y]==0)dfs(_x,_y); } } int main() { cin>>n>>m; for(int i=1;i<=n;i+=1)cin>>c[i]+1; while(m--) { cin>>x>>y; if(!d[x][y]) { e.clear(); cnt=0; dfs(x,y); for(auto i:e)d[i.first][i.second]=cnt; } cout<<d[x][y]<<'\n'; } }
- 1
信息
- ID
- 772
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 104
- 已通过
- 42
- 上传者