版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_42369449/article/details/82806784
**算法:并查集**
难度:(NOIP-)
其实这道题可以不用并查集,直接bfs即可,但是这个搜索是有技巧的,不能暴搜!
首先,容易发现,只在所有自己的城市建水泵一定是最优解,所以,根据这条性质我们来bfs
对自己的城市按高度排序,该城市不用建的前提是从他出发经过一条高度都小于等于他的路径能到达一个已经修建水泵的城市!
技巧:用循环来取代深搜,可以防止回溯不清楚的问题,循环中直接return,就可以结束整个函数了!
1.0 错误贪心+dfs!
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <queue>
#define N 1005
using namespace std;
int mapp[N][N];
int vis[N][N];
int viss[N][N];
int fa[N];
struct node
{
int x,y;
int val;
}poi[N*N];
int findf(int x)
{
if(x==fa[x]) return x;
return fa[x]=findf(fa[x]);
}
int cmp(node a,node b)
{
return a.val<b.val;
}
int fla,ans,cnt,n,m;
int dx[6]={0,1,-1,0,0};
int dy[6]={0,0,0,1,-1};
void bfs(int x,int y)
{
if(fla==cnt)
{
printf("%d\n",ans);
exit(0);
}
if(x<=0||y<=0||x>n||y>m) return;
if(viss[x][y]) return;
if(vis[x][y])
{
fla++;
}
viss[x][y]=1;
for(int i = 1;i <= 4;i++)
{
if(x+dx[i]<=0||y+dy[i]<=0||x+dx[i]>n||y+dy[i]>m) continue;
if(mapp[x][y]>mapp[x+dx[i]][y+dy[i]]) continue;
bfs(x+dx[i],y+dy[i]);
}
}
int main()
{
scanf("%d%d",&n,&m);
//memset(mapp,0x3f3f3f3f,sizeof(mapp));
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
int he;
scanf("%d",&he);
if(he>0)
{
vis[i][j]=1;
++cnt;
poi[cnt].x=i;
poi[cnt].y=j;
poi[cnt].val=he;
mapp[i][j]=he;
}else
{
mapp[i][j]=-he;
}
}
}
sort(poi+1,poi+1+cnt,cmp);
for(int i = 1;i <= cnt;i++)
{
if(viss[poi[i].x][poi[i].y]) continue;
ans++;
bfs(poi[i].x,poi[i].y);
}
if(fla==cnt)
{
printf("%d\n",ans);
exit(0);
}
return 0 ;
}
/*/
3 2
-1 -1 -3
-2 9 100
6 -4 -5
*/
2.0 bfs(AC)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <queue>
#define N 1005
using namespace std;
int vis[N][N],viss[N][N];
int mapp[N][N];
int dx[6]={-1,1,0,0},dy[6]={0,0,-1,1};
struct node
{
int x;int y;int he;
}poi[N*N];
int cmp(node a,node b)
{
return a.he<b.he;
}
int ctt;
int qx[N*N],qy[N*N],bo[N][N];
int pre=0;
int bfs(int x,int y)
{
pre++;
bo[x][y]=pre;
qx[1]=x,qy[1]=y;
int h=1,t=1,nx,ny,nh=mapp[x][y];
while(h<=t)
{
nx=qx[h];
ny=qy[h++];
for(int i = 0;i < 4;i++)
{
int xx=nx+dx[i],yy=ny+dy[i];
if(vis[xx][yy]&&bo[xx][yy]!=pre&&mapp[xx][yy]<=nh)
{
bo[xx][yy]=pre;
qx[++t]=xx;qy[t]=yy;
if(viss[xx][yy]) return 1;
}
}
}
return 0;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int cnt=0;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
vis[i][j]=1;
int x;
scanf("%d",&x);
if(x>0)
{
mapp[i][j]=x;
poi[++cnt].x=i;
poi[cnt].y=j;
poi[cnt].he=x;
bo[i][j]=1;
}else mapp[i][j]=-x;
}
}
sort(poi+1,poi+1+cnt,cmp);
int ans=0;
for(int i = 1;i <= cnt;i++)
{
if(!bfs(poi[i].x,poi[i].y)) ans++;
viss[poi[i].x][poi[i].y]=1;
}
printf("%d\n",ans);
return 0 ;
}