L - Farm Irrigation (并查集
给你一个管道地图,求联通块个数
很简单的并查集,简单预处理输入一下
但zoj能过,hdu就是莫名其妙的wa
后来发现是我地图的表示时边界的处理有问题
例如
ABD
KJH
KNG
我把这个矩阵读取成一行:ABDKJHKNG
对于第i个元素 上下左右就表示为 ut=i - n ,lt=i -1 ,rt=i+1 ,dt=i+n;
判断边界: ut>0 i%n !=1 i%n !=0 dt<=m*n
这样平常没什么问题,所以zoj能过
但是。。。 当矩阵宽度为1时,左右边界就会合并,这时判断 左边界 i%n !=1 就会出错,因为此时“余1” 就是 余0
所以要特判一下1.。。。
以后这种情况要特别注意(不过再碰到题我可能就不这样表示上下左右了)
#include <cstdio> #include <iostream> #include <string> #include <cstring> #include <algorithm> using namespace std; int pre[500000]; int node[500000]; const int u[50 ]={1,1,0,0,1,0,1,1,0,1,1}; const int l [50 ]={1,0,1,0,0,1,1,1,1,0,1}; const int r [50 ]={0,1,0,1,0,1,1,0,1,1,1}; const int d[50 ]={0,0,1,1,1,0,0,1,1,1,1}; void init( int n){ for( int i=0 ;i<=n;i++) pre[i] = i; } int find( int x){ int r= x; while( pre[x] != x){ x= pre[x]; } int t; while( r!=x){ t = pre[r]; pre[r] = x; r = t; } return x; } void add( int a ,int b){ // cout<<a <<' '<<b<<endl; int x=find(a); int y=find(b); if( x!=y) pre[x] =y; return ; } int main( ){ int m ,n; while( cin>>m>>n){ if( m<0 || n<0) break; int an = m*n; init( an); string op; int cnt = 1; for( int i=1 ;i<=m ;i++){ cin>> op; for( int j=0 ; j<n ;j++) node[cnt++] =(int)(op[j]-'A'); } for( int i=1 ;i<=an ;i++){ int t=node[i]; int ut=i - n ,lt=i -1 ,rt=i+1 ,dt=i+n; if( u[ t] && ut>0 && d[ node[ut] ])add(i ,ut); if( l[ t] && i%n !=1 && n !=1 && r[ node[lt] ])add(i ,lt); //就是这一行 if( r[ t] && i%n !=0 && n !=1&& l[ node[rt] ])add(i ,rt); if( d[ t] && dt<=an && u[ node[dt] ])add(i ,dt); } int ans=0; for( int i=1 ; i<=an ;i++){ if( pre[i] == i)ans++; // cout<<i<<' '<<pre[i]<<endl; } printf("%d\n" ,ans); } return 0; }