题意:
给出一个滑雪场,并且规定奶牛只能向他相邻的并且高度不大于他的点运动,现在想要在某些点对之间加上缆车使得奶牛可以从较低点向较高点运动,问最少需要多少辆缆车可以使得奶牛滑倒每一各角落。
分析:
可以看出来,如果高度相同,那么就是一个强连通分量,缩点后进行计算。这里采用bfs进行缩点计算,也可以用taijan。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=510;
int g[maxn][maxn],ss[maxn*maxn];
bool vis[maxn*maxn];
int in[maxn*maxn],out[maxn*maxn];
int n,m,con;
struct node{
int t,s;
}que[maxn*maxn];
void bfs(){
con=0;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!vis[i*m+j]){
int st=1,en=1;
que[en].t=i;
que[en++].s=j;
vis[i*m+j]=1;
while(st<en){
int t=que[st].t;
int s=que[st++].s;
for(int p=-1;p<=1;p++){
for(int q=-1;q<=1;q++){
if(abs(p)+abs(q)==1&&t+p<=n&&t+p>=1&&s+q<=m&&s+q>=1){
if(g[t][s]==g[t+p][s+q]){
if(!vis[(t+p)*m+s+q]){
vis[(t+p)*m+s+q]=1;
que[en].t=t+p;
que[en++].s=s+q;
}
}
}
}
}
}
con++;
for(int i=1;i<en;i++){
ss[que[i].t*m+que[i].s]=con;
}
}
}
}
}
int main(){
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&g[i][j]);
}
}
bfs();
memset(in,0,sizeof in);
memset(out,0,sizeof out);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int p=-1;p<=1;p++){
for(int q=-1;q<=1;q++){
if(abs(p)+abs(q)==1&&i+p<=n&&i+p>=1&&j+q<=m&&j+q>=1){
if(g[i][j]>=g[i+p][j+q]){
if(ss[(i+p)*m+j+q]!=ss[i*m+j]){
in[ss[i*m+j]]++;
out[ss[(i+p)*m+j+q]]++;
}
}
}
}
}
}
}
if(con<=1){
printf("0\n");
}else{
int numin=0,numout=0;
for(int i=1;i<=con;i++){
if(in[i]==0) numin++;
if(out[i]==0) numout++;
}
printf("%d\n",max(numin,numout));
}
}
return 0;
}