呐,你想成为什么颜色? ——《樱花庄的宠物女孩》
题目:https://www.luogu.org/problem/P1141
花了点时间把这题搞定,看到标签中的“高性能”后真的吓一跳,最怕这种题了——
因为它永远永远肯定是要优化的。
而我最不会的就是优化。
于是一开始,我就是用暴力bfs来搞的,然后抱着试一试的心态交了一下,果不其然炸三个点,TLE了。
然后想着改进方式,仔细一想,好像一次bfs后会把一些数组标记掉,让它无法重复走;而且这些在同一次标记过的点中,无论从那个点出发,走到的点数是一样的!
这么一想,似乎就明了了——
联通块!!!
你以为我会告诉你我其实一开始没想到的,是看了题解才知道的吗
其实还有一件事,我习惯在bfs时,在开头用memset重置一下,但这题因为要重置的数组太大(1000000),每次搜索重置,绝对会炸掉,因此我在用了联通块后还是TLE掉两个点,蓝瘦。
好了,那么废话不说,上代码:
#include<bits/stdc++.h>//这题连通图思想很关键 using namespace std; int dx[5]={0,1,-1,0,0}; int dy[5]={0,0,0,-1,1}; int n,m,ans=1; int sx,sy; int sum[1000005]; char a[1005][1005]; int b[1005][1005];//把它变成一个连通图 ,同一连通图中值相等 int h[1000005][4]; int head=0,tail=0,tu=0;//tu用来记录连通图数量 void bfs(int x,int y) { tu++; head=0;tail=1;ans=1; h[1][1]=x,h[1][2]=y,h[1][3]=int(a[x][y]); b[x][y]=tu; while(head<tail) { head++; for(int i=1;i<=4;i++) { int xx=dx[i]+h[head][1]; int yy=dy[i]+h[head][2]; if(!b[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<n&&int(a[xx][yy])!=h[head][3]) { tail++; h[tail][1]=xx; h[tail][2]=yy; h[tail][3]=int(a[xx][yy]); b[xx][yy]=tu; ans++; } } } sum[tu]=ans; } int main() { memset(b,0,sizeof(b)); memset(h,0,sizeof(h)); //放搜索外面,不然每次搜索都要重置一遍很费时间的 //毕竟h数组很大啊 scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",a[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&sx,&sy); sx--;sy--; if(b[sx][sy]==0) bfs(sx,sy); printf("%d ",sum[b[sx][sy]]); //因为要算的包括自己,所以要加1 } return 0; }