pku 1235 Galactic Breakup 并查集
题意:一个帝国有N个国家组成,每个国家包括N i个区域(一个小方格),然后第i个国家在第i月会分离出去。问有多少个月帝国仍然是一个整体。
PS:说道帝国,就想到黄金雄教授在ICPC开幕式上用闽南语讲的(。。。ACM大帝国。。),那发音,拿语言的组织都超级搞笑

思路:
并查集,逆向思维。最后所有的国家应该都是独立的。相当于一个国家一个国家逐月的联合起来。用并查集统计是否当前集合为一个整体即可。暴力的方法没实验过,不过复杂度会高达30^6,(*^__^*) 嘻嘻……,RP好的可以去拼一下~
代码:
1
//
============================================================================
2 // Name : pku1235.cpp
3 // Author : yzhw
4 // Version :
5 // Copyright : yzhw
6 // Description : Hello World in C++, Ansi-style
7 // ============================================================================
8
9 #include < iostream >
10 #include < cstdio >
11 #include < vector >
12 #include < algorithm >
13 using namespace std;
14 # define LEFT (data[i][j] % (n * m))
15 int set [ 30000 ],n,m,k,l,data[ 30000 ][ 21 ];
16 bool used[ 30000 ];
17 int find( int pos)
18 {
19 if ( set [pos] == pos) return pos;
20 else return set [pos] = find( set [pos]);
21 }
22 int main() {
23 int testcase;
24 scanf( " %d " , & testcase);
25 while (testcase -- )
26 {
27 scanf( " %d%d%d%d " , & n, & m, & k, & l);
28 int total = 0 ,ans = 0 ,c;
29 for ( int i = 0 ;i < n * m * k;i ++ )
30 set [i] = i,used[i] = false ;
31 for ( int i = 0 ;i < l;i ++ )
32 {
33 scanf( " %d " , & data[i][ 0 ]);
34 for ( int j = 1 ;j <= data[i][ 0 ];j ++ )
35 scanf( " %d " , & data[i][j]);
36 }
37 for ( int i = l - 1 ;i >= 0 ;i -- )
38 {
39 c = 0 ;
40 for ( int j = 1 ;j <= data[i][ 0 ];j ++ )
41 {
42 vector < int > refer;
43 if (data[i][j] - n * m >= 0 && used[data[i][j] - n * m]) refer.push_back(find(data[i][j] - n * m));
44 if (data[i][j] + n * m < n * m * k && used[data[i][j] + n * m]) refer.push_back(find(data[i][j] + n * m));
45 if (LEFT % n != 0 && used[data[i][j] - 1 ]) refer.push_back(find(data[i][j] - 1 ));
46 if (LEFT % n != n - 1 && used[data[i][j] + 1 ]) refer.push_back(find(data[i][j] + 1 ));
47 if (LEFT / n != 0 && used[data[i][j] - n]) refer.push_back(find(data[i][j] - n));
48 if (LEFT / n != m - 1 && used[data[i][j] + n]) refer.push_back(find(data[i][j] + n));
49 sort(refer.begin(),refer.end());
50 vector < int > ::iterator end = unique(refer.begin(),refer.end());
51 c += end - refer.begin();
52 for ( int t = 0 ;t < end - refer.begin();t ++ )
53 set [find(refer[t])] = find(data[i][j]);
54 used[data[i][j]] = true ;
55 }
56 total = total + data[i][ 0 ] - c;
57 if (total == 1 ) ans ++ ;
58 }
59 printf( " %d\n " ,l - ans);
60 }
61 return 0 ;
62 }
2 // Name : pku1235.cpp
3 // Author : yzhw
4 // Version :
5 // Copyright : yzhw
6 // Description : Hello World in C++, Ansi-style
7 // ============================================================================
8
9 #include < iostream >
10 #include < cstdio >
11 #include < vector >
12 #include < algorithm >
13 using namespace std;
14 # define LEFT (data[i][j] % (n * m))
15 int set [ 30000 ],n,m,k,l,data[ 30000 ][ 21 ];
16 bool used[ 30000 ];
17 int find( int pos)
18 {
19 if ( set [pos] == pos) return pos;
20 else return set [pos] = find( set [pos]);
21 }
22 int main() {
23 int testcase;
24 scanf( " %d " , & testcase);
25 while (testcase -- )
26 {
27 scanf( " %d%d%d%d " , & n, & m, & k, & l);
28 int total = 0 ,ans = 0 ,c;
29 for ( int i = 0 ;i < n * m * k;i ++ )
30 set [i] = i,used[i] = false ;
31 for ( int i = 0 ;i < l;i ++ )
32 {
33 scanf( " %d " , & data[i][ 0 ]);
34 for ( int j = 1 ;j <= data[i][ 0 ];j ++ )
35 scanf( " %d " , & data[i][j]);
36 }
37 for ( int i = l - 1 ;i >= 0 ;i -- )
38 {
39 c = 0 ;
40 for ( int j = 1 ;j <= data[i][ 0 ];j ++ )
41 {
42 vector < int > refer;
43 if (data[i][j] - n * m >= 0 && used[data[i][j] - n * m]) refer.push_back(find(data[i][j] - n * m));
44 if (data[i][j] + n * m < n * m * k && used[data[i][j] + n * m]) refer.push_back(find(data[i][j] + n * m));
45 if (LEFT % n != 0 && used[data[i][j] - 1 ]) refer.push_back(find(data[i][j] - 1 ));
46 if (LEFT % n != n - 1 && used[data[i][j] + 1 ]) refer.push_back(find(data[i][j] + 1 ));
47 if (LEFT / n != 0 && used[data[i][j] - n]) refer.push_back(find(data[i][j] - n));
48 if (LEFT / n != m - 1 && used[data[i][j] + n]) refer.push_back(find(data[i][j] + n));
49 sort(refer.begin(),refer.end());
50 vector < int > ::iterator end = unique(refer.begin(),refer.end());
51 c += end - refer.begin();
52 for ( int t = 0 ;t < end - refer.begin();t ++ )
53 set [find(refer[t])] = find(data[i][j]);
54 used[data[i][j]] = true ;
55 }
56 total = total + data[i][ 0 ] - c;
57 if (total == 1 ) ans ++ ;
58 }
59 printf( " %d\n " ,l - ans);
60 }
61 return 0 ;
62 }