1 条题解
-
0

// SCC 缩点 Tarjan 算法 O(N) #include<bits/stdc++.h> using namespace std; const int N=250005,M=4*N; int to[M],ne[M],h[N],idx; void add(int a,int b){ to[++idx]=b,ne[idx]=h[a],h[a]=idx; } int n,m,a[505][505]; int dfn[N],low[N],stk[N],top,scc[N],cnt; int in[N],out[N],s1,s2; int get(int i,int j){return (i-1)*m+j;} //格点的编号 void ade(int i,int j){ if(i>1){ if(a[i][j]>=a[i-1][j]) add(get(i,j),get(i-1,j)); //向上连边 if(a[i][j]<=a[i-1][j]) add(get(i-1,j),get(i,j)); //向下连边 } if(j>1){ if(a[i][j]>=a[i][j-1]) add(get(i,j),get(i,j-1)); //向左连边 if(a[i][j]<=a[i][j-1]) add(get(i,j-1),get(i,j)); //向右连边 } } void tarjan(int x){ //SCC缩点 dfn[x]=low[x]=++dfn[0]; stk[++top]=x; for(int i=h[x];i;i=ne[i]){ int y=to[i]; if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if(!scc[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ ++cnt; while(stk[top+1]!=x) scc[stk[top--]]=cnt; //缩点的编号 } } int main(){ scanf("%d%d",&m,&n); //m列n行 for(int i=1;i<=n;++i)for(int j=1;j<=m;++j) scanf("%d",&a[i][j]),ade(i,j); //连边 for(int i=1;i<=n*m;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=n*m;++i)for(int j=h[i];j;j=ne[j]) //枚举每个格点的出边 if(scc[i]!=scc[to[j]]) ++in[scc[to[j]]],++out[scc[i]]; for(int i=1;i<=cnt;++i){ if(!in[i]) ++s1; //入度为0的缩点个数 if(!out[i]) ++s2; //出度为0的缩点个数 } printf("%d",cnt==1?0:max(s1,s2)); return 0; }
- 1
信息
- ID
- 2184
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 2
- 上传者