You are on page 1of 87

Standard Code Library

Hao Yuan
Department of Computer Science and Engineering
Shanghai Jiaotong University

October 23, 2003


Contents

1 Algorithms and Datastructures 3


1.1 High Precision in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 High Precision in C Plus Plus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 High Precision Floating-point Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Fraction Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Binary Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 Winner Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.7 Digital Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.8 Segment Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.9 Segment Tree in IOI’2001 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.10 Union-Find Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.11 Quick Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.12 Merge Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.13 Radix Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.14 Select K th Smallest Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.15 KMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.16 Suffix Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2 Graph Theory and Network Algorithms 14


2.1 SSSP — Dijkstra + Binary Heap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2 SSSP — Bellman Ford + Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3 MST — Kruskal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4 Minimum Directed Spanning Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5 Maximum Matching on Bipartite Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.6 Maximum Cost Perfect Matching on Bipartite Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.7 Maximum Matching on General Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.8 Maximum Flow — Ford Fulkson in Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.9 Maximum Flow — Ford Fulkson in Link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.10 Minimum Cost Maximum Flow in Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.11 Minimum Cost Maximum Flow in Link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.12 Recognizing Chordal Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.13 DFS — Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.14 DFS — Cutvertex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.15 DFS — Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.16 DFS — Topological Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.17 Strongly Connected Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3 Number Theory 25
3.1 Greatest Common Divisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2 Chinese Remainder Theorem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3 Prime Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.4 φ Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.5 Discrete Logarithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.6 Square Roots in Zp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4 Algebraic Algorithms 29
4.1 Linear Equations in Z2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.2 Linear Equations in Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.3 Linear Equations in Q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.4 Linear Equations in R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.5 Roots of Polynomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

1
4.6 Roots of Cubic and Quartic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.7 Fast Fourier Transform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.8 FFT - Polynomial Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.9 FFT - Convolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.10 FFT - Reverse Bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.11 Linear Programming - Primal Simplex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

5 Computational Geometry 38
5.1 Basic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.2 Extended Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3 Convex Hull . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.4 Point Set Diameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.5 Closest Pair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.6 Circles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.7 Largest Empty Convex Polygon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.8 Triangle Centers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.9 Polyhedron Volume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.10 Planar Graph Contour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.11 Rectangles Area . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.12 Rectangles Perimeter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.13 Smallest Enclosing Circle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
5.14 Smallest Enclosing Ball . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

6 Classic Problems 57
6.1 Bernoulli Number Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.2 Baltic OI’99 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.3 Bead Coloring — Pólya Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.4 Binary Stirling Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.5 Box Surface Distance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.6 Calculate Expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.7 Cartesian Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.8 Catalan Number Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.9 Coloring Regular Polygon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6.10 Counting Inverse Pairs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
6.11 Counting Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.12 Eight Puzzle Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.13 Extended Honai Tower . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
6.14 High Precision Square Root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
6.15 Largest Empty Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.16 Last Non-Zero Digit of N! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.17 Least Common Ancestor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
6.18 Longest Common Substring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
6.19 Longest Non Descending Sub Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.20 Join and Disjoin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
6.21 Magic Square . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
6.22 Optimal Binary Search Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.23 Pack Rectangles — Cut Rectangles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.24 Pack Rectangles — O(N 2 ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.25 Parliament . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.26 π Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
6.27 Plant Trees — Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.28 Plant Trees — Segment Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.29 Range Maximum Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.30 Travelling Salesman Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
6.31 Tree Heights . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.32 Minimum Cyclic Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.33 Maximum Clique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
6.34 Maximal Non-Forbidden Submatrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.35 Maximum Two Chain Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.36 N Queens Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.37 de Bruijn Sequence Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.38 ZOJ 1482 Partition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

2
while ( c . s [ i ] ) { c . s [ i +1]=c . s [ i ] / 1 0 ; c . s [ i ]%=10; i ++; }
while ( i >1 && ! c . s [ i ] ) i −−; c . l e n=i ;
return c ;
}

HP HP : : operator+(const HP &b )
{
int i ; HP c ; c . s [ 1 ] = 0 ;
fo r ( i = 1 ; i<=l e n | | i<=b . l e n | | c . s [ i ] ; i ++) {
i f ( i<=l e n ) c . s [ i ]+=s [ i ] ;
i f ( i<=b . l e n ) c . s [ i ]+=b . s [ i ] ;
c . s [ i +1]=c . s [ i ] / 1 0 ; c . s [ i ]%=10;
}
c . l e n=i − 1 ; i f ( c . l e n ==0 ) c . l e n =1;
return c ;
}

HP HP : : operator −(const HP &b )


{
int i , j ; HP c ;
fo r ( i =1, j = 0 ; i<=l e n ; i ++) {
c . s [ i ]= s [ i ]− j ; i f ( i<=b . l e n ) c . s [ i ]−=b . s [ i ] ;
i f ( c . s [ i ] < 0 ) { j = 1 ; c . s [ i ] + = 1 0 ; } e l s e j =0;
}
c . l e n=l e n ; while ( c . l e n >1 && ! c . s [ c . l e n ] ) c . l e n −−;
return c ;
}

int HP : : Compare ( const HP &y )


{
i f ( l e n >y . l e n ) return 1 ;
i f ( l e n <y . l e n ) return −1;
int i=l e n ;
while ( ( i >1)&&( s [ i ]==y . s [ i ] ) ) i −−;
return s [ i ]−y . s [ i ] ;
}

HP HP : : operator / ( const HP &b )


{
int i , j ; HP d ( 0 ) , c ;
fo r ( i=l e n ; i >0; i −−) {
i f ( ! ( d . l e n ==1 && d . s [ 1 ] = = 0 ) )
{ f or ( j=d . l e n ; j >0; j −−) d . s [ j +1]=d . s [ j ]; ++ d . l e n ; }
d . s [1]= s [ i ] ; c . s [ i ]=0;
while ( ( j=d . Compare ( b)) >=0 )
{ d=d−b ; c . s [ i ]++; i f ( j ==0) break ; }
}
c . l e n=l e n ; while ( ( c . l e n >1)&&(c . s [ c . l e n ]==0)) c . l e n −−;
return c ;
}

HP HP : : operator%(const HP &b )
{
int i , j ; HP d ( 0 ) ;
fo r ( i=l e n ; i >0; i −−) {
i f ( ! ( d . l e n ==1 && d . s [ 1 ] = = 0 ) )
{ f or ( j=d . l e n ; j >0; j −−) d . s [ j +1]=d . s [ j ]; ++ d . l e n ; }
d . s [1]= s [ i ] ;
while ( ( j=d . Compare ( b )) >=0 ){ d=d−b ; i f ( j ==0) break ; }
}
return d ;
}

5
Chapter 1

Algorithms and Datastructures

1.1 High Precision in C


#define maxlen 1 0 0 0

struct HP { int l e n , s [ maxlen ] ; } ;

void PrintHP (HP x ) { for ( int i=x . l e n ; i >=1; i −−) cout<<x . s [ i ] ; }

void Str2HP ( const char ∗ s ,HP &x )


{
x . l e n=s t r l e n ( s ) ;
fo r ( int i =1; i<=x . l e n ; i ++) x . s [ i ]= s [ x . l e n −i ]− ’ 0 ’ ;
}

void Int2HP ( int i n t e ,HP &x )


{
i f ( i n t e ==0) { x . l e n = 1 ; x . s [ 1 ] = 0 ; return ; } ;
fo r ( x . l e n =0; i n t e > 0 ; ) { x . s[++x . l e n ]= i n t e %10; i n t e / = 1 0 ; } ;
}

void Multi ( const HP a , const HP b ,HP & c )


{
int i , j ; c . l e n=a . l e n+b . l e n ;
fo r ( i =1; i<=c . l e n ; i ++) c . s [ i ] = 0 ;
fo r ( i =1; i<=a . l e n ; i ++) for ( j =1; j<=b . l e n ; j ++) c . s [ i+j −1]+=a . s [ i ] ∗ b . s [ j ] ;
fo r ( i =1; i <c . l e n ; i ++) { c . s [ i +1]+=c . s [ i ] / 1 0 ; c . s [ i ]%=10; }
while ( c . s [ i ] ) { c . s [ i +1]=c . s [ i ] / 1 0 ; c . s [ i ]%=10; i ++; }
while ( i >1 && ! c . s [ i ] ) i −−; c . l e n=i ;
}

void Plus ( const HP a , const HP b ,HP & c )


{
int i ; c . s [ 1 ] = 0 ;
fo r ( i = 1 ; i<=a . l e n | | i<=b . l e n | | c . s [ i ] ; i ++) {
i f ( i<=a . l e n ) c . s [ i ]+=a . s [ i ] ;
i f ( i<=b . l e n ) c . s [ i ]+=b . s [ i ] ;
c . s [ i +1]=c . s [ i ] / 1 0 ; c . s [ i ]%=10;
}
c . l e n=i − 1 ; i f ( c . l e n ==0 ) c . l e n =1;
}

void S u b t r a c t ( const HP a , const HP b ,HP & c )


{
fo r ( int i =1, j = 0 ; i<=a . l e n ; i ++) {
c . s [ i ]=a . s [ i ]− j ; i f ( i<=b . l e n ) c . s [ i ]−=b . s [ i ] ;
i f ( c . s [ i ] < 0 ) { j = 1 ; c . s [ i ] + = 1 0 ; } e l s e j =0;
}

3
c . l e n=a . l e n ; while ( c . l e n >1 && ! c . s [ c . l e n ] ) c . l e n −−;
}

int HPCompare ( const HP x , const HP y )


{
i f ( x . l e n >y . l e n ) return 1 ;
i f ( x . l e n <y . l e n ) return −1;
int i=x . l e n ;
while ( ( i >1)&&(x . s [ i ]==y . s [ i ] ) ) i −−;
return x . s [ i ]−y . s [ i ] ;
}

void D i v i d e ( const HP a , const HP b , HP &c ,HP &d )


{
int i , j ; d . l e n = 1 ; d . s [ 1 ] = 0 ;
fo r ( i=a . l e n ; i >0; i −−) {
i f ( ! ( d . l e n ==1 && d . s [ 1 ] = = 0 ) )
{ f or ( j=d . l e n ; j >0; j −−) d . s [ j +1]=d . s [ j ]; ++ d . l e n ; }
d . s [1]= a . s [ i ] ; c . s [ i ]=0;
while ( ( j=HPCompare ( d , b)) >=0 )
{ S u b t r a c t ( d , b , d ) ; c . s [ i ]++; i f ( j ==0) break ; }
}
c . l e n=a . l e n ; while ( ( c . l e n >1)&&(c . s [ c . l e n ]==0)) c . l e n −−;
}

1.2 High Precision in C Plus Plus


const int maxlen = 1 0 0 0 0 ;

c l a s s HP { public :
int l e n , s [ maxlen ] ; HP( ) { ( ∗ t h i s ) = 0 ; } ;
HP( int i n t e ) { ( ∗ t h i s )= i n t e ; } ; HP( const char∗ s t r ) { ( ∗ t h i s )= s t r ; } ;
friend ostream & operator<<(ostream & cout , const HP &x ) ;
HP operator=( int i n t e ) ; HP operator=(const char∗ s t r ) ;
HP operator ∗ ( const HP &b ) ; HP operator+(const HP &b ) ;
HP operator −(const HP &b ) ; HP operator / ( const HP &b ) ;
HP operator%(const HP &b ) ; int Compare ( const HP &b ) ;
};

ostream & operator<<(ostream & cout , const HP &x )


{ for ( int i=x . l e n ; i >=1; i −−) cout<<x . s [ i ] ; return c o u t ; }

HP HP : : operator=(const char ∗ s t r )
{
l e n=s t r l e n ( s t r ) ;
fo r ( int i =1; i<=l e n ; i ++) s [ i ]= s t r [ l e n −i ]− ’ 0 ’ ;
return ∗ t h i s ;
}

HP HP : : operator=( int i n t e )
{
i f ( i n t e ==0) { l e n = 1 ; s [ 1 ] = 0 ; return ( ∗ t h i s ) ; } ;
fo r ( l e n =0; i n t e > 0 ; ) { s[++ l e n ]= i n t e %10; i n t e / = 1 0 ; } ;
return ( ∗ t h i s ) ;
}

HP HP : : operator ∗ ( const HP &b )


{
int i , j ; HP c ; c . l e n=l e n+b . l e n ;
fo r ( i =1; i<=c . l e n ; i ++) c . s [ i ] = 0 ;
fo r ( i =1; i<=l e n ; i ++) for ( j =1; j<=b . l e n ; j ++) c . s [ i+j −1]+=s [ i ] ∗ b . s [ j ] ;
fo r ( i =1; i <c . l e n ; i ++) { c . s [ i +1]+=c . s [ i ] / 1 0 ; c . s [ i ]%=10; }

4
1.3 High Precision Floating-point Number

const int f p r e c = 1 0 0 ; // f l o a t i n g −p o i n t p r e c i s i o n

HP z e r o =0;

c l a s s FS{ public :
FS ( ) ; void S e t Z e r o ( ) ;
FS ( int i n t e ) { ( ∗ t h i s )= i n t e ; }
FS ( char ∗ s ) { ( ∗ t h i s )= s ; }
FS operator=(char ∗ s ) ; FS operator=( int i n t e ) ;
FS operator+(FS b ) ; FS operator −(FS b ) ;
FS operator ∗ ( FS b ) ; FS operator / (FS b ) ;
friend ostream & operator<<(ostream & cout , FS x ) ;
int s i g n , p r e c ;
HP num ;
};

void FS : : S e t Z e r o ( ) { s i g n = 1 ; num= 0 ; p r e c = 0 ; }

FS : : FS ( ) { S e t Z e r o ( ) ; }

ostream & operator<<(ostream & cout , FS x )


{
i f ( x . s i g n <0) cout<<”−” ;
int i , k , low =1;
fo r ( i=x . num . l e n ; i >x . p r e c ; i −−) cout<<x . num . s [ i ] ;
i f ( x . num . l e n<=x . p r e c ) cout<<”0” ;
i f ( x . num . Compare ( z e r o ) = = 0 ) { cout<<” . 0 ” ; return c o u t ; }
k=i ;
while ( k>0 && x . num . s [ k ] = = 0 ) k−−;
i f ( k ==0) { cout<<” . 0 ” ; return c o u t ; }
cout<<” . ” ;
i f ( x . num . l e n <x . p r e c ) for ( int j =0; j <x . prec−x . num . l e n ; j ++) cout<<” 0 ” ;
while ( x . num . s [ low ]==0) low++;
while ( i>=low ) cout<<x . num . s [ i −−];
return c o u t ;
}

FS FS : : operator=( int i n t e )
{
prec = 0;
i f ( i n t e >=0 ) { s i g n = 1 ; num = i n t e ; }
else { s i g n = −1; num = − i n t e ; }
return ( ∗ t h i s ) ;
}

FS FS : : operator=(char ∗ s )
{
int p , i , j , l ;
SetZero ( ) ;
i f ( s [0]== ’− ’ ) { s i g n = −1; s ++; };
i f ( s [0]== ’+ ’ ) { s i g n = 1 ; s ++; };
l = strlen (s );
fo r ( p = 0 ; p<l ; p++) i f ( s [ p]== ’ . ’ ) break ;
i f ( p==l ) p r e c = 0 ; e l s e p r e c = l −1−p ;
fo r ( i=l −1, j = 0 ; i >=0; i −−) i f ( s [ i ] ! = ’ . ’ ) num . s[++ j ] = s [ i ]− ’ 0 ’ ;
while ( j >1 && num . s [ j ]==0) −− j ; num . l e n = j ;
return ( ∗ t h i s ) ;
}

6
void L S h i f t ( FS &a , int s l )
{
a . p r e c+=s l ; a . num . l e n+=s l ; int i ;
fo r ( i=a . num . l e n ; i >s l ; i −−) a . num . s [ i ]=a . num . s [ i −s l ] ;
while ( i >0) a . num . s [ i −−]=0;
}

void R S h i f t ( FS &a , int s l )


{
a . prec−=s l ; a . num . l e n−=s l ; int i ;
fo r ( i = 1 ; i<=a . num . l e n ; i ++) a . num . s [ i ]=a . num . s [ i+s l ] ;
}

FS FS : : operator+(FS b )
{
FS c ;
i f ( prec>b . p r e c ) L S h i f t ( b , prec−b . p r e c ) ; e l s e
i f ( prec<b . p r e c ) L S h i f t ( ( ∗ t h i s ) , b . prec−p r e c ) ;
i f ( s i g n==b . s i g n ) {
c . s i g n=s i g n ; c . p r e c=p r e c ; c . num=num+b . num ;
i f ( c . num . Compare ( z e r o )==0 ) c . S e t Z e r o ( ) ;
} else {
c . p r e c=p r e c ;
i f ( num . Compare ( b . num)==0) c . S e t Z e r o ( ) ; e l s e
i f ( num . Compare ( b . num) > 0 ) { c . s i g n=s i g n ; c . num=num−b . num ; } e l s e
i f ( num . Compare ( b . num) < 0 ) { c . s i g n=b . s i g n ; c . num=b . num−num ; }
i f ( c . num . Compare ( z e r o )==0 ) c . S e t Z e r o ( ) ;
}
i f ( c . prec > fprec ) RShift ( c , c . prec − fprec ) ;
return c ;
}

FS FS : : operator −(FS b )
{
b . sign = − b . sign ;
FS c = ( ∗ t h i s ) + b ;
b . sign = − b . sign ;
return c ;
}

FS FS : : operator ∗ ( FS b )
{
FS c ;
c . sign = sign ∗ b . sign ;
c . prec = prec + b . prec ;
c . num = num ∗ b . num ;
i f ( c . num . Compare ( z e r o )==0 ) c . S e t Z e r o ( ) ;
i f ( c . prec > fprec ) RShift ( c , c . prec − fprec ) ;
return c ;
}

FS FS : : operator / (FS b ) // 355/133 = 3.1415929203539823008849557522124


{
FS c , d ; // c = d / b
d = (∗ this ) ; LShift (d , f p r e c ) ;
c . sign = d . sign ∗ b . sign ;
c . prec = d . prec ;
LShift (d , b . prec ) ;
c . num = d . num / b . num ;
i f ( c . prec > fprec ) RShift ( c , c . prec − fprec ) ;
return c ;
}

7
1.4 Fraction Class
int gcd ( int a , int b ) { i f ( b==0) return a ; return gcd ( b , a%b ) ; }
int lcm ( int a , int b ) { return a/ gcd ( a , b ) ∗ b ; }

c l a s s F r a c t i o n { public :
int a , b ; // ( a/ b = numerator / denominator )
int s i g n ( int x ) { return ( x >0?1: −1 ); }
Fraction ( ) : a (0) , b(1){}
F r a c t i o n ( int x ) : a ( x ) , b ( 1 ) { }
F r a c t i o n ( int x , int y ) {
int m = gcd ( abs ( x ) , abs ( y ) ) ;
a = x/m ∗ s i g n ( y ) ;
i f ( a==0) b = 1 ; e l s e b = abs ( y/m ) ;
}
int g e t d e n o m i n a t o r ( ) { return b ; }
int g e t n u m e r a t o r ( ) { return a ; }
F r a c t i o n operator+(const F r a c t i o n & f ) {
int m = gcd ( b , f . b ) ;
return F r a c t i o n ( f . b/m ∗ a + b/m ∗ f . a , b/m ∗ f . b ) ;
}
F r a c t i o n operator −(const F r a c t i o n & f ) {
int m = gcd ( b , f . b ) ;
return F r a c t i o n ( f . b/m ∗ a − b/m ∗ f . a , b/m ∗ f . b ) ;
}
F r a c t i o n operator ∗ ( const F r a c t i o n & f ) {
int m1 = gcd ( abs ( a ) , f . b ) ;
int m2 = gcd ( b , abs ( f . a ) ) ;
return F r a c t i o n ( ( a/m1) ∗ ( f . a/m2 ) , ( b/m2) ∗ ( f . b/m1 ) ) ;
}
F r a c t i o n operator / ( const F r a c t i o n & f )
{ return ( ∗ t h i s ) ∗ F r a c t i o n ( f . b , f . a ) ; }
friend ostream &operator<<(ostream & out , const F r a c t i o n & f ) {
i f ( f . a==0) c o u t < < 0; e l s e
i f ( f . b==1) c o u t << f . a ; e l s e c o u t << f . a << ’ / ’ << f . b ;
return out ;
}
};

1.5 Binary Heap


#define MAXN 1 0 4 8 5 7 6
int n , HeapSize , Heap [MAXN+ 1 ] ;

void HeapUp ( int p )


{
int q=p>>1,a=Heap [ p ] ;
while ( q ) {
i f ( a<Heap [ q ] ) Heap [ p]=Heap [ q ] ; e l s e break ;
p=q ; q=p > > 1;
}
Heap [ p]=a ;
}

void AddToHeap ( int a )


{
Heap[++HeapSize ]=a ;
HeapUp ( HeapSize ) ;
}

8
void HeapDown ( int p )
{
int q=p<<1,a=Heap [ p ] ;
while ( q <= HeapSize ) {
i f ( q<HeapSize && Heap [ q+1]<Heap [ q ] ) q++;
i f ( Heap [ q ] < a ) Heap [ p ] = Heap [ q ] ; e l s e break ;
p=q ; q=p < < 1;
}
Heap [ p ] = a ;
}

int GetTopFromHeap ( )
{
int TopElement = Heap [ 1 ] ;
Heap [ 1 ] = Heap [ HeapSize −−];
HeapDown ( 1 ) ;
return TopElement ;
}

void BuildHeap ( ) // Remember t o Let HeapSize = N


{ for ( int i=HeapSize ; i >0; i −−) HeapDown ( i ) ; }

1.6 Winner Tree


const int i n f =10000000;
const int maxsize =1 0 4 8 5 7 6 ; // 2 ˆ f l o o r ( l o g ( n ) )

int heap [ maxsize ∗ 2 ] , pos [ maxsize ∗ 2 ] , n , b a s e ;

void Update ( int i )


{
int j=i <<1;
i f ( heap [ j +1]<heap [ j ] ) j ++;
heap [ i ]= heap [ j ] ; pos [ i ]= pos [ j ] ;
}

int GetTopFromHeap ( int & ps )


{
int r e t=heap [ 1 ] , p=pos [ 1 ] ;
ps=p ; heap [ p]= i n f ;
while ( p > 1 ) { p>>=1; Update ( p ) ; }
return r e t ;
}

int main ( )
{
int i , j ;
c i n >> n ;
fo r ( b a s e =1; base<n ; base <<=1); base −−;
fo r ( i=b a s e +1; i <=(base <<1)+1; i ++) {
pos [ i ]= i ;
i f ( i<=b a s e+n ) c i n >> heap [ i ] ; e l s e heap [ i ]= i n f ;
}
fo r ( i=b a s e ; i >0; i −−) Update ( i ) ;
fo r ( i =1; i<=n ; i ++) cout<<GetTopFromHeap ( j )<<e n d l ;
return 0 ;
}

9
1.7 Digital Tree
#define maxlen 1 0 0
#define maxsize 1 0 0 0 0 0 0
#define DataType int

char t r e e [ maxsize ] , s [ maxlen ] ;


int son [ maxsize ] , bro [ maxsize ] , num , k , n ;
DataType data [ maxsize ] ;

DataType f i n d ( const char∗ s )


{
int i , j =0;
fo r ( i =0; s [ i ] ; i ++) {
j=son [ j ] ;
while ( j && t r e e [ j ] ! = s [ i ] ) j=bro [ j ] ;
i f ( ! j ) return −1;
}
return data [ j ] ;
}

void add ( const char∗ s , DataType x )


{
int i , j =0,p ;
fo r ( i =0; s [ i ] ; i ++) {
p=j ; j=son [ j ] ;
while ( j && t r e e [ j ] ! = s [ i ] ) j=bro [ j ] ;
if (! j ) {
t r e e [++num]= s [ i ] ; son [ num] = 0 ;
bro [ num]= son [ p ] ; son [ p]=num ;
data [ num]= −1; j=num ;
}
}
data [ j ]=x ;
}

void i n i t ( )
{ num= 0 ; bro [ num ] = 0 ; son [ num ] = 0 ; data [ 0 ] = − 1 ; }

1.8 Segment Tree


int c c [ 1 < < 2 2 ] ,m, n ; // memset cc f i r s t

void update ( int i i , int s , int t , int s s , int t t , bool i n s e r t ) {


i f ( s s >t t ) return ; int mid ( ( s+t ) / 2 ) ;
i f ( s==s s && t==t t ) { i f ( i n s e r t ) c c [ i i ]= t−s + 1 ; e l s e c c [ i i ] = 0 ; return ; }
i f ( c c [ i i ]==0) i f ( ! i n s e r t ) return ; e l s e c c [ i i ∗2]= c c [ i i ∗2+1]=0;
e l s e i f ( c c [ i i ]==t−s +1) i f ( i n s e r t ) return ;
e l s e { c c [ i i ∗2]=mid−s + 1 ; c c [ i i ∗2+1]= t−mid ; }
update ( i i ∗ 2 , s , mid , s s , m i n ( mid , t t ) , i n s e r t ) ;
update ( i i ∗2+1 ,mid+1, t , max ( mid+1, s s ) , t t , i n s e r t ) ;
c c [ i i ]= c c [ i i ∗2]+ c c [ i i ∗ 2 + 1 ] ;
}

int query ( int i i , int s , int t , int s s , int t t ) {


i f ( s s >t t ) return 0 ; int mid ( ( s+t ) / 2 ) ;
i f ( s==s s && t==t t ) return c c [ i i ] ;
i f ( c c [ i i ]==0) c c [ i i ∗ 2 ] = c c [ i i ∗ 2 + 1 ] = 0 ;
i f ( c c [ i i ]==t−s +1) { c c [ i i ∗2]=mid−s + 1 ; c c [ i i ∗2+1]= t−mid ; }
return query ( i i ∗ 2 , s , mid , s s , m i n ( mid , t t ) )
+query ( i i ∗2+1 ,mid+1, t , max ( mid+1, s s ) , t t ) ;
}

10
1.9 Segment Tree in IOI’2001
// upper : maximum p o s s i b l e r i g h t p o i n t o f i n t e r v a l s
int upper , t r e e [ m a x i n t e r v a l + 1 ] ;

void i n i t ( )
{ upper = 0 ; memset ( t r e e , 0 , s i z e o f ( t r e e ) ) ; }

void update ( int r , int x ) // sum [ 1 . . r ] += x


{ while ( r<=upper ) { t r e e [ r]+=x ; r+=(r &( r ˆ ( r − 1 ) ) ) ; } }

int sum ( int r ) // r e t u r n sum [ 1 . . r ]


{
int r e s = 0 ;
while ( r > 0 ) { r e s+=t r e e [ r ] ; r −=(r &( r ˆ ( r − 1 ) ) ) ; }
return r e s ;
}

1.10 Union-Find Set


int rank [ maxn ] , pnt [ maxn ] ;

void makeset ( int x )


{ rank [ pnt [ x]=x ] = 0 ; }

int f i n d ( int x )
{
int px=x , i ;
while ( px!= pnt [ px ] ) px=pnt [ px ] ;
while ( x!=px ) { i=pnt [ x ] ; pnt [ x]=px ; x=i ; } ;
return px ;
}

void merge ( int x , int y ) // or j u s t pnt [ f i n d ( x )]= f i n d ( y )


{
i f ( rank [ x=f i n d ( x )] > rank [ y=f i n d ( y ) ] ) pnt [ y]=x ;
e l s e { pnt [ x]=y ; rank [ y]+=( rank [ x]==rank [ y ] ) ; } ;
}

1.11 Quick Sort


void q u i c k s o r t ( int b , int e , int a [ ] )
{
int i=b , j=e , x=a [ ( b+e ) / 2 ] ;
do{
while ( a [ i ]<x ) i ++;
while ( a [ j ]>x ) j −−;
i f ( i<=j ) s t d : : swap ( a [ i ++],a [ j − −]);
} while ( i <j ) ;
i f ( i <e ) q u i c k s o r t ( i , e , a ) ;
i f ( j >b ) q u i c k s o r t ( b , j , a ) ;
}

11
1.12 Merge Sort
void s o r t ( int b , int e )
{
i f ( e−b<=0) return ;
int mid=(b+e ) / 2 , p1=b , p2=mid+1, i=b ;
s o r t ( b , mid ) ; s o r t ( mid+1, e ) ;
while ( p1<=mid | | p2<=e )
i f ( p2>e | | ( p1<=mid && a [ p1]<=a [ p2 ] ) )
t [ i ++]=a [ p1 ++]; e l s e t [ i ++]=a [ p2 ++];
fo r ( i=b ; i<=e ; i ++)a [ i ]= t [ i ] ;
}

1.13 Radix Sort


#define b a s e (1 < <16)
int n , a [ maxn ] , t [ maxn ] , bucket [ b a s e + 2 ] ;

void RadixSort ( int n , int a [ ] , int t [ ] , int bucket [ ] )


{
int k , i , j ;
fo r ( j =0; j <b a s e ; j ++) bucket [ j ] = 0 ;
fo r ( k=base −1, i = 0 ; i < 2 ; i ++,k<<=16){
f o r ( j =0; j <n ; j ++) bucket [ a [ j ]&k]++;
f o r ( j =1; j <b a s e ; j ++) bucket [ j ]+=bucket [ j − 1 ] ;
f o r ( j=n−1; j >=0; j −−) t[−−bucket [ a [ j ]&k ] ] = a [ j ] ;
f o r ( j =0; j <n ; j ++) a [ j ]= t [ j ] ;
}
}

1.14 Select K th Smallest Element


int s e l e c t ( int ∗ a , int b , int e , int k )
{
i f ( b==e ) return a [ b ] ;
int x = a [ b+rand ()%( e−b + 1 ) ] , i = b , j = e ;
i −−; j ++;
while ( i <j ) {
while ( a[++ i ] < x ) ; while ( a[−− j ] > x ) ;
i f ( i <j ) s t d : : swap ( a [ i ] , a [ j ] ) ;
}
i f ( j==e ) j −−; i = j −b+1;
i f ( k <= i ) return s e l e c t ( a , b , j , k ) ;
e l s e return s e l e c t ( a , j +1 , e , k−i ) ;
}

1.15 KMP
int f a i l [ maxlen ] ;

void m a k e f a i l ( char ∗ t , int l t )


{
−−t ;
fo r ( int i =1, j =0; i<=l t ; i ++, j ++){
f a i l [ i ]= j ;
while ( j >0 && t [ i ] ! = t [ j ] ) j= f a i l [ j ] ;
}
}

// s t a r t matching p a t t e r n T i n S [ i . . )
// r e t u r n match pos or l o n g e s t match l e n g t h w i t h c o r r e s p o n d i n g pos

12
int kmp( char ∗ s , int l s , char ∗ t , int l t , int i , int & l o n g e s t , int & l p )
{
l o n g e s t = l p = 0; − − s ; −− t ;
fo r ( int j = 1 ; i<=l s ; i ++, j ++) {
while ( j >0 && s [ i ] ! = t [ j ] ) j= f a i l [ j ] ;
i f ( j >l o n g e s t ) { l o n g e s t = j ; l p = i −j ; }
i f ( j==l t ) return i −l t ;
}
return −1;
}

1.16 Suffix Sort


SuffixSort : input s[0..n) , output id[0..n)

#define nb next // ” new b u c k e t ” o v e r l a i d on ” n e x t ”


#define head h e i g h t // head i s n e v e r used when computing h e i g h t
#define rank b // a f t e r S u f f i x S o r t , ” rank ” o v e r l a i d on ” b u c k e t ”

char s [ maxn ] ; int n , i d [ maxn ] , h e i g h t [ maxn ] , b [ maxn ] , next [ maxn ] ;

bool cmp( const int & i , const int & j ) { return s [ i ]< s [ j ] ; }

void S u f f i x S o r t ( )
{
int i , j , k , h ;
fo r ( i = 0 ; i <n ; i ++) i d [ i ]= i ;
s t d : : s o r t ( id , i d+n , cmp ) ;
fo r ( i = 0 ; i <n ; i ++)
i f ( i ==0 || s [ id [ i ] ] ! = s [ id [ i − 1 ] ] ) b [ id [ i ] ] = i ;
else b [ id [ i ]]=b [ id [ i −1]];
fo r ( h = 1 ; h<n ; h<<=1)
{
f o r ( i =0; i <n ; i ++) head [ i ]= next [ i ]= −1;
f o r ( i=n − 1 ; i >=0; i −−) i f ( i d [ i ] )
{
j = i d [ i ]−h ; i f ( j < 0 ) j+=n ;
next [ j ] = head [ b [ j ] ] ; head [ b [ j ] ] = j ;
}
j=n−h ; next [ j ] = head [ b [ j ] ] ; head [ b [ j ] ] = j ;
f o r ( i=k = 0 ; i <n ; i ++) i f ( head [ i ] >=0 )
f o r ( j=head [ i ] ; j >=0; j=next [ j ] ) i d [ k++]= j ;
f o r ( i = 0 ; i <n ; i ++) i f ( i >0 && i d [ i ]+h<n && i d [ i −1]+h<n
&& b [ i d [ i ] ] = = b [ i d [ i −1]] && b [ i d [ i ]+h ] == b [ i d [ i −1]+h ] )
nb [ i d [ i ] ] = nb [ i d [ i − 1 ] ] ; e l s e nb [ i d [ i ] ] = i ;
f o r ( i = 0 ; i <n ; i ++) b [ i ] = nb [ i ] ;
}
}
GetHeight : height[i] = LCP (s[id[i]], s[id[i] − 1]

void GetHeight ( )
{
int i , j , h ; h e i g h t [ 0 ] = 0 ;
fo r ( i = 0 ; i <n ; i ++) rank [ i d [ i ] ] = i ;
fo r ( h =0 , i = 0 ; i <n ; i ++ ) i f ( rank [ i ] > 0 )
{
j = i d [ rank [ i ] − 1 ] ;
while ( s [ i+h ] == s [ j+h ] ) + + h ;
h e i g h t [ rank [ i ] ] = h ;
i f ( h>0 ) −−h ;
}
}
13
Chapter 2

Graph Theory and Network Algorithms

2.1 SSSP — Dijkstra + Binary Heap


const int i n f = 1 0 0 0 0 0 0 0 0 0 ;

int n ,m, num , l e n , next [ maxm ] , ev [ maxm ] , ew [ maxm ] ;


int v a l u e [ maxn ] , mk [ maxn ] , nbs [ maxn ] , ps [ maxn ] , heap [ maxn ] ;

void update ( int r )


{
int q=ps [ r ] , p=q>>1;
while ( p && v a l u e [ heap [ p ]] > v a l u e [ r ] ) {
ps [ heap [ p ] ] = q ; heap [ q]= heap [ p ] ;
q=p ; p=q>>1;
}
heap [ q]= r ; ps [ r ]=q ;
}

int getmin ( )
{
int r e t=heap [ 1 ] , p=1,q=2, r=heap [ l e n −−];
while ( q<=l e n ) {
i f ( q<l e n && v a l u e [ heap [ q+1]] < v a l u e [ heap [ q ] ] ) q++;
i f ( v a l u e [ heap [ q ]] < v a l u e [ r ] ) {
ps [ heap [ q ] ] = p ; heap [ p]= heap [ q ] ;
p=q ; q=p<<1;
} e l s e break ;
}
heap [ p]= r ; ps [ r ]=p ;
return r e t ;
}

void d i j k s t r a ( int s r c , int d s t )


{
int i , j , u , v ;
fo r ( i =1; i<=n ; i ++) { v a l u e [ i ]= i n f ; mk [ i ]= ps [ i ] = 0 ; } ;
v a l u e [ s r c ] = 0 ; heap [ l e n =1]= s r c ; ps [ s r c ] = 1 ;
while ( ! mk [ d s t ] ) {
i f ( l e n ==0) return ;
u=getmin ( ) ; mk [ u ] = 1 ;
f o r ( j=nbs [ u ] ; j ; j=next [ j ] ) {
v=ev [ j ] ; i f ( ! mk [ v ] && v a l u e [ u]+ew [ j ]< v a l u e [ v ] ) {
i f ( ps [ v ]==0){ heap[++ l e n ]=v ; ps [ v]= l e n ; }
v a l u e [ v]= v a l u e [ u]+ew [ j ] ; update ( v ) ;
}
}
}
}

14
void r e a d d a t a ( )
{
int i , u , v ,w ;
c i n >>n>>m; num=0;
fo r ( i =1; i<=n ; i ++) nbs [ i ] = 0 ;
while (m−−){
c i n >>u>>v>>w;
next[++num]= nbs [ u ] ; nbs [ u]=num ;
ev [ num]=v ; ew [ num]=w;
}
d i j k s t r a ( 1 , n ) ; // Minimum D i s t a n c e s a v e d a t v a l u e [ 1 . . n ]
}

2.2 SSSP — Bellman Ford + Queue


const int maxn = maxm = 1000005
const int i n f = 1000000000

int nbs [ maxn ] , next [ maxm ] , v a l u e [ maxn ] , open [ maxn ] , open1 [ maxn ] ;
int ev [ maxm ] , ew [ maxm ] , mk [ maxn ] , n ,m, num , cur , t a i l ;

void BellmanFord ( int s r c )


{
int i , j , k , l , t , u , v , p=0;
fo r ( i =1; i<=n ; i ++) { v a l u e [ i ]= i n f ; mk [ i ] = 0 ; }
v a l u e [ s r c ]= t a i l = 0 ; open [ 0 ] = s r c ;
while(++p , t a i l >=0){
f o r ( i =0; i<=t a i l ; i ++) open1 [ i ]= open [ i ] ;
f o r ( c u r =0, t=t a i l , t a i l =−1; cur<=t ; c u r++)
f o r ( u=open1 [ c u r ] , i=nbs [ u ] ; i ; i=next [ i ] ) {
v=ev [ i ] ; i f ( v a l u e [ u]+ew [ i ]< v a l u e [ v ] ) {
v a l u e [ v]= v a l u e [ u]+ew [ i ] ;
i f (mk [ v ] ! = p ) { open[++ t a i l ]=v ; mk [ v]=p ; }
}
}
}
}

2.3 MST — Kruskal


#define maxn 1 0 0 0 0 0 5
#define maxm 1 0 0 0 0 0 5

int i d [ maxm ] , eu [ maxm ] , ev [ maxm ] , ew [ maxm ] , n ,m, pnt [ maxn ] ;


int cmp( const int & i , const int & j ) { return ew [ i ]<ew [ j ] ; }
int f i n d ( int x ) { i f ( x!= pnt [ x ] ) pnt [ x]= f i n d ( pnt [ x ] ) ; return pnt [ x ] ; }

int Kruskal ( )
{
int r e t =0, i , j , p ;
fo r ( i =1; i<=n ; i ++) pnt [ i ]= i ; // node [ 1 . . n ]
fo r ( i =0; i <m; i ++) i d [ i ]= i ; // ew [ 0 . . m−1]
s t d : : s o r t ( id , i d+m, cmp ) ;
fo r ( j =−1, i = 1 ; i <n ; i ++){
while ( p=i d [++ j ] , f i n d ( eu [ p])== f i n d ( ev [ p ] ) ) ;
r e t+=ew [ p ] ; pnt [ f i n d ( ev [ p ] ) ] = f i n d ( eu [ p ] ) ;
}
return r e t ;
}

15
2.4 Minimum Directed Spanning Tree
int n , g [ maxn ] [ maxn ] , used [ maxn ] , p a s s [ maxn ] , eg [ maxn ] , more , queue [ maxn ] ;

void combine ( int id , int & sum ) {


int t o t = 0 , from , i , j , k ;
fo r ( ; i d !=0&&! p a s s [ i d ] ; i d=eg [ i d ] ) { queue [ t o t++]=i d ; p a s s [ i d ] = 1 ; }
fo r ( from = 0 ; from<t o t&&queue [ from ] ! = i d ; from ++);
i f ( from==t o t ) return ; more = 1 ;
fo r ( i=from ; i <t o t ; i ++) {
sum+=g [ eg [ queue [ i ] ] ] [ queue [ i ] ] ;
i f ( i != from ) { used [ queue [ i ] ] = 1 ;
f o r ( j = 1 ; j <= n ; j ++) i f ( ! used [ j ] )
i f ( g [ queue [ i ] ] [ j ]<g [ i d ] [ j ] ) g [ i d ] [ j ]=g [ queue [ i ] ] [ j ] ;
}
}
fo r ( i = 1 ; i<=n ; i ++) i f ( ! used [ i ]&& i != i d ) {
f o r ( j=from ; j <t o t ; j ++){ k=queue [ j ] ;
i f ( g [ i ] [ i d ]>g [ i ] [ k]−g [ eg [ k ] ] [ k ] ) g [ i ] [ i d ]=g [ i ] [ k]−g [ eg [ k ] ] [ k ] ;
}
}
}

int msdt ( int r o o t ) { // r e t u r n t h e t o t a l l e n g t h o f MDST


int i , j , k , sum = 0 ;
memset ( used , 0 , s i z e o f ( used ) ) ;
fo r ( more = 1 ; more ; ) { more = 0 ;
memset ( eg , 0 , s i z e o f ( eg ) ) ;
f o r ( i = 1 ; i <= n ; i ++) i f ( ! used [ i ] && i ! = r o o t ) {
f o r ( j = 1 , k = 0 ; j <= n ; j ++) i f ( ! used [ j ] && i ! = j )
if ( k == 0 || g [ j ] [ i ] < g [ k ] [ i ] ) k = j ;
eg [ i ] = k ;
} memset ( pass , 0 , s i z e o f ( p a s s ) ) ;
f o r ( i =1; i<=n ; i ++) i f ( ! used [ i ]&&! p a s s [ i ]&& i != r o o t ) combine ( i , sum ) ;
}
fo r ( i = 1 ; i<=n ; i ++) i f ( ! used [ i ] && i != r o o t ) sum+=g [ eg [ i ] ] [ i ] ;
return sum ;
}

2.5 Maximum Matching on Bipartite Graph


int nx , ny ,m, g [MAXN] [MAXN] , sy [MAXN] , cx [MAXN] , cy [MAXN] ;

int path ( int u )


{
fo r ( int v=1;v<=ny ; v++) i f ( g [ u ] [ v ] & & ! sy [ v ] ) { sy [ v ] = 1 ;
i f ( ! cy [ v ] | | path ( cy [ v ] ) ) { cx [ u]=v ; cy [ v]=u ; return 1 ; }
} return 0 ;
}

int MaximumMatch ( )
{
int i , r e t =0;
memset ( cx , 0 , s i z e o f ( cx ) ) ; memset ( cy , 0 , s i z e o f ( cy ) ) ;
fo r ( i =1; i<=nx ; i ++) i f ( ! cx [ i ] ) { memset ( sy , 0 , s i z e o f ( sy ) ) ; r e t+=path ( i ) ; }
return r e t ;
}

16
2.6 Maximum Cost Perfect Matching on Bipartite Graph
int cx [ maxn ] , cy [ maxn ] , sx [ maxn ] , sy [ maxn ] , l x [ maxn ] , l y [ maxn ] ;
int nx , ny , match , g [ maxn ] [ maxn ] ;

int path ( int u)


{
sx [ u ] = 1 ; f o r ( int v=1;v<=ny ; v++) i f ( g [ u ] [ v]== l x [ u]+ l y [ v ] & & ! sy [ v ] ) {
sy [ v ] = 1 ; i f ( ! cy [ v ] | | path ( cy [ v ] ) ) { cx [ u]=v ; cy [ v]=u ; return 1 ; }
} return 0;
}

void KuhnMunkres ( )
{
int i , j , u , min ;
memset ( lx , 0 , s i z e o f ( l x ) ) ; memset ( ly , 0 , s i z e o f ( l y ) ) ;
memset ( cx , 0 , s i z e o f ( cx ) ) ; memset ( cy , 0 , s i z e o f ( cy ) ) ;
fo r ( i =1; i<=nx ; i ++) for ( j =1; j<=ny ; j ++) i f ( l x [ i ]<g [ i ] [ j ] ) l x [ i ]=g [ i ] [ j ] ;
fo r ( match =0 , u = 1 ; u<=nx ; u++) i f ( ! cx [ u ] ) {
memset ( sx , 0 , s i z e o f ( sx ) ) ; memset ( sy , 0 , s i z e o f ( sy ) ) ;
while ( ! path ( u ) ) {
min=0 x 3 f f f f f f f ;
f o r ( i =1; i<=nx ; i ++) i f ( sx [ i ] ) f o r ( j =1; j<=ny ; j ++) i f ( ! sy [ j ] )
i f ( l x [ i ]+ l y [ j ]−g [ i ] [ j ]<min ) min=l x [ i ]+ l y [ j ]−g [ i ] [ j ] ;
f o r ( i =1; i<=nx ; i ++) i f ( sx [ i ] ) { l x [ i ]−=min ; sx [ i ] = 0 ; }
f o r ( j =1; j<=ny ; j ++) i f ( sy [ j ] ) { l y [ j ]+=min ; sy [ j ] = 0 ; }
};
}
}

2.7 Maximum Matching on General Graph


// t o t a l i s t h e maximum c a r d i n a l i t y , p [ 1 . . n ] means a match : i <−> p [ i ]
int g [ maxn ] [ maxn ] , p [ maxn ] , l [ maxn ] [ 3 ] , n , t o t a l , s t a t u s [ maxn ] , v i s i t e d [ maxn ] ;

void s o l v e ( )
{
int i , j , k , p a s s ;
memset ( p , 0 , s i z e o f ( p ) ) ;
do { i =0;
do { i f ( p[++ i ] ) p a s s = 0 ; e l s e {
memset ( l , 0 , s i z e o f ( l ) ) ;
l [ i ] [ 2 ] = 0 x f f ; p a s s=path ( i ) ;
for ( j =1; j<=n ; j ++) for ( k=1;k<=n ; k++)
i f ( g [ j ] [ k ] < 0 ) g [ j ] [ k]=−g [ j ] [ k ] ;
};
} while ( i !=n && ! p a s s ) ;
i f ( p a s s ) t o t a l +=2;
} while ( i !=n && t o t a l !=n ) ;
}

void upgrade ( int r )


{
int j=r , i=l [ r ] [ 1 ] ;
fo r ( p [ i ]= j ; l [ i ] [ 2 ] < 0 x f f ; ) {
p [ j ]= i ; j=l [ i ] [ 2 ] ; i=l [ j ] [ 1 ] ; p [ i ]= j ;
} p [ j ]= i ;
}

17
int path ( int r )
{
int i , j , k , v , t , q u i t ;
memset ( s t a t u s , 0 , s i z e o f ( s t a t u s ) ) ; s t a t u s [ r ] = 2 ;
do { q u i t =1;
f o r ( i =1; i<=n ; i ++) i f ( s t a t u s [ i ] >1)
f o r ( j =1; j<=n ; j ++) i f ( g [ i ] [ j ]>0 && p [ j ] ! = i )
i f ( s t a t u s [ j ]==0) {
i f ( p [ j ]==0){ l [ j ] [ 1 ] = i ; upgrade ( j ) ; return 1 ; } e l s e
i f (p [ j ] >0) {
g [ i ] [ j ]=g [ j ] [ i ]= −1; s t a t u s [ j ] = 1 ;
l [ j ] [ 1 ] = i ; g [ j ] [ p [ j ] ] = g [ p [ j ] ] [ j ]= −1;
l [p[ j ]][2]= j ; status [ p [ j ]]=2;
q u i t =0;
}
} else
i f ( s t a t u s [ j ] >1 && ( s t a t u s [ i ]+ s t a t u s [ j ] <6)){
q u i t = 0 ; g [ i ] [ j ]=g [ j ] [ i ]= −1;
memset ( v i s i t e d , 0 , s i z e o f ( v i s i t e d ) ) ;
visited [ i ]=1; k=i ; v=2;
while ( l [ k ] [ v ] ! = 0 x f f ) { k=l [ k ] [ v ] ; v=3−v ; v i s i t e d [ k ] = 1 ; }
k=j ; v=2;
while ( ! v i s i t e d [ k ] ) { k=l [ k ] [ v ] ; v=3−v ; }
if ( status [ i ]!=3) l [ i ][1]= j ;
if ( status [ j ]!=3) l [ j ][1]= i ;
s t a t u s [ i ]= s t a t u s [ j ] = 3 ; t=i ; v=2;
while ( t !=k ) {
i f ( s t a t u s [ l [ t ] [ v ] ] ! = 3 ) l [ l [ t ] [ v ] ] [ v]= t ;
t=l [ t ] [ v ] ; s t a t u s [ t ] = 3 ; v=3−v ;
}
t=j ; v=2;
while ( t !=k ) {
i f ( s t a t u s [ l [ t ] [ v ] ] ! = 3 ) l [ l [ t ] [ v ] ] [ v]= t ;
t=l [ t ] [ v ] ; s t a t u s [ t ] = 3 ; v=3−v ;
}
}
} while ( ! q u i t ) ;
return 0 ;
}

2.8 Maximum Flow — Ford Fulkson in Matrix


// Remember t o memset C[ maxn ] [ maxn ] f o r a new c a s e
int c [ maxn ] [ maxn ] , f [ maxn ] [ maxn ] , pnt [ maxn ] , open [ maxn ] , d [ maxn ] , mk [ maxn ] ;

int maxflow ( int n , int s , int t )


{
int cur , t a i l , i , j , u , v , f l o w = 0 ; memset ( f , 0 , s i z e o f ( f ) ) ;
do { memset (mk, 0 , s i z e o f (mk ) ) ; memset ( d , 0 , s i z e o f ( d ) ) ;
open [ 0 ] = s ; mk [ s ] = 1 ; d [ s ]=0 x 3 f f f f f f f ;
f o r ( pnt [ s ]= c u r= t a i l = 0 ; cur<=t a i l && !mk [ t ] ; c u r++)
f o r ( u=open [ c u r ] , v=1;v<=n ; v++) i f ( ! mk [ v]&& f [ u ] [ v]< c [ u ] [ v ] ) {
mk [ v ] = 1 ; open[++ t a i l ]=v ; pnt [ v]=u ;
i f ( d [ u]< c [ u ] [ v]− f [ u ] [ v ] ) d [ v]=d [ u ] ;
e l s e d [ v]= c [ u ] [ v]− f [ u ] [ v ] ;
}
i f ( ! mk [ t ] ) break ; f l o w+=d [ t ] ;
f o r ( u=t ; u!= s ; ) { v=u ; u=pnt [ v ] ; f [ u ] [ v]+=d [ t ] ; f [ v ] [ u]=− f [ u ] [ v ] ; }
} while ( d [ t ] > 0 ) ; return f l o w ;
}

18
2.9 Maximum Flow — Ford Fulkson in Link
#define maxn 1 0 0 0
#define maxm 2 ∗ maxn∗maxn

int c [ maxm ] , f [ maxm ] , ev [ maxm ] , be [ maxm ] , next [ maxm ] , num=0;


int nbs [ maxn ] , pnt [ maxn ] , open [ maxn ] , d [ maxn ] , mk [ maxn ] ;

void AddEdge ( int u , int v , int c c ) // Remember t o s e t nbs [ 1 . . n]=num=0


{
next[++num]= nbs [ u ] ; nbs [ u]=num ; be [ num]=num+1;
ev [ num]=v ; c [ num]= c c ; f [ num] = 0 ;
next[++num]= nbs [ v ] ; nbs [ v]=num ; be [ num]=num−1;
ev [ num]=u ; c [ num ] = 0 ; f [ num] = 0 ;
}

int maxflow ( int n , int s , int t )


{
int cur , t a i l , i , j , u , v , f l o w = 0 ; // f has been s e t z e r o when AddEdge
do { memset (mk, 0 , s i z e o f (mk ) ) ; memset ( d , 0 , s i z e o f ( d ) ) ;
open [ 0 ] = s ; mk [ s ] = 1 ; d [ s ]=0 x 3 f f f f f f f ;
f o r ( pnt [ s ]= c u r= t a i l = 0 ; cur<=t a i l && !mk [ t ] ; c u r++)
f o r ( u=open [ c u r ] , j=nbs [ u ] ; j ; j=next [ j ] ) { v=ev [ j ] ;
i f ( ! mk [ v]&& f [ j ]< c [ j ] ) {
mk [ v ] = 1 ; open[++ t a i l ]=v ; pnt [ v]= j ;
i f ( d [ u]< c [ j ]− f [ j ] ) d [ v]=d [ u ] ; e l s e d [ v]= c [ j ]− f [ j ] ;
}
}
i f ( ! mk [ t ] ) break ; f l o w+=d [ t ] ;
f o r ( u=t ; u!= s ; u=ev [ be [ j ] ] ) { j=pnt [ u ] ; f [ j ]+=d [ t ] ; f [ be [ j ]]=− f [ j ] ; }
} while ( d [ t ] > 0 ) ; return f l o w ;
}

19
2.10 Minimum Cost Maximum Flow in Matrix
const int i n f =0 x 3 f f f f f f f ;

int c [ maxn ] [ maxn ] , f [ maxn ] [ maxn ] ,w[ maxn ] [ maxn ] , pnt [ maxn ] ;
int v a l u e [ maxn ] , d [ maxn ] , mk [ maxn ] , open [ maxn ] , o l d q u e [ maxn ] ;

void m i n c o s t ( int n , int s , int t , int & flow , int & c o s t )


{
int cur , t a i l , t l , i , j , u , v ;
memset ( f , 0 , s i z e o f ( f ) ) ; f l o w = 0 ; c o s t =0;
do { memset ( d , 0 , s i z e o f ( d ) ) ;
f o r ( i =1; i<=n ; i ++) v a l u e [ i ]= i n f ;
open [ 0 ] = s ; d [ s ]=0 x 3 f f f f f f f ; t a i l =v a l u e [ s ] = 0 ;
while ( t a i l >=0){
memset (mk, 0 , s i z e o f (mk ) ) ;
memcpy( oldque , open , s i z e o f ( open ) ) ;
f o r ( t l=t a i l , pnt [ s ]= c u r =0, t a i l =−1; cur<=t l ; c u r++)
f o r ( u=o l d q u e [ c u r ] , v=1;v<=n ; v++)
i f ( f [ u ] [ v]< c [ u ] [ v ] && v a l u e [ u]< i n f
&& v a l u e [ u]+w[ u ] [ v]< v a l u e [ v ] ) {
i f ( ! mk [ v ] ) { mk [ v ] = 1 ; open[++ t a i l ]=v ; } ;
pnt [ v]=u ; v a l u e [ v]= v a l u e [ u]+w [ u ] [ v ] ;
i f ( d [ u]< c [ u ] [ v]− f [ u ] [ v ] ) d [ v]=d [ u ] ;
e l s e d [ v]= c [ u ] [ v]− f [ u ] [ v ] ;
}
}
i f ( v a l u e [ t]== i n f ) return ;
f l o w+=d [ t ] ; c o s t+=d [ t ] ∗ v a l u e [ t ] ;
f o r ( u=t ; u!= s ; ) {
v=u ; u=pnt [ v ] ; f [ u ] [ v]+=d [ t ] ; f [ v ] [ u]=− f [ u ] [ v ] ;
i f ( f [ u ] [ v ] < 0 ) w[ u ] [ v]=−w [ v ] [ u ] ; e l s e
i f ( f [ v ] [ u ] < 0 ) w[ v ] [ u]=−w [ u ] [ v ] ;
}
} while ( d [ t ] > 0 ) ;
}

20
2.11 Minimum Cost Maximum Flow in Link
#define maxn 3 5 0
#define maxm 1 0 0 0 0 0 // maxm∗2
const int i n f =0 x 3 f f f f f f f ;

int c [ maxm ] , f [ maxm ] ,w[ maxm ] , ev [ maxm ] , be [ maxm ] , next [ maxm ] , v a l u e [ maxn ] ;
int nbs [ maxn ] , pnt [ maxn ] , open [ maxn ] , o l d q u e [ maxn ] , d [ maxn ] , mk [ maxn ] , num=0;

void AddEdge ( int u , int v , int cc , int ww) // Remember t o s e t nbs [ 1 . . n]=num=0
{
next[++num]= nbs [ u ] ; nbs [ u]=num ; be [ num]=num+1;
ev [ num]=v ; c [ num]= c c ; f [ num ] = 0 ; w [ num]=ww;
next[++num]= nbs [ v ] ; nbs [ v]=num ; be [ num]=num−1;
ev [ num]=u ; c [ num ] = 0 ; f [ num ] = 0 ; w [ num]=−ww;
}

void m i n c o s t ( int n , int s , int t , int & flow , int & c o s t )


{
int cur , t a i l , t l , i , j , u , v ;
memset ( f , 0 , s i z e o f ( f ) ) ; f l o w = 0 ; c o s t =0;
do { memset ( d , 0 , s i z e o f ( d ) ) ;
f o r ( i =1; i<=n ; i ++) v a l u e [ i ]= i n f ;
open [ 0 ] = s ; d [ s ]=0 x 3 f f f f f f f ; t a i l =v a l u e [ s ] = 0 ;
while ( t a i l >=0){
memset (mk, 0 , s i z e o f (mk ) ) ;
memcpy( oldque , open , s i z e o f ( open ) ) ;
f o r ( t l=t a i l , pnt [ s ]= c u r =0, t a i l =−1; cur<=t l ; c u r++)
f o r ( u=o l d q u e [ c u r ] , j=nbs [ u ] ; j ; j=next [ j ] ) { v=ev [ j ] ;
i f ( f [ j ]< c [ j ] && v a l u e [ u]< i n f && v a l u e [ u]+w [ j ]< v a l u e [ v ] ) {
i f ( ! mk [ v ] ) { mk [ v ] = 1 ; open[++ t a i l ]=v ; } ;
pnt [ v]= j ; v a l u e [ v]= v a l u e [ u]+w [ j ] ;
i f ( d [ u]< c [ j ]− f [ j ] ) d [ v]=d [ u ] ; e l s e d [ v]= c [ j ]− f [ j ] ;
}
}
}
i f ( v a l u e [ t]== i n f ) return ;
f l o w+=d [ t ] ; c o s t+=d [ t ] ∗ v a l u e [ t ] ;
f o r ( u=t ; u!= s ; u=ev [ be [ j ] ] ) { j=pnt [ u ] ; f [ j ]+=d [ t ] ; f [ be [ j ]]=− f [ j ] ; }
} while ( d [ t ] > 0 ) ;
}

2.12 Recognizing Chordal Graph


int n ,m, mk [ maxn ] , d e g r e e [ maxn ] ,PEO[ maxn ] , g [ maxn ] [ maxn ] ;

int Chordal ( )
{
memset (mk, 0 , s i z e o f (mk ) ) ; memset ( d e g r e e , 0 , s i z e o f ( d e g r e e ) ) ;
fo r ( int j , k , u , v , i =0; i <n ; i ++) {
j =−1; u=−1;
f o r ( k=0;k<n ; k++) i f ( ! mk [ k ] & & ( j < 0 | | d e g r e e [ k]> d e g r e e [ j ] ) ) j=k ;
mk [ j ] = 1 ; PEO[ i ]= j ;
f o r ( k=i −1;k>=0;k−−) i f ( g [ j ] [ PEO[ k ] ] )
i f ( u < 0 ) u=PEO[ k ] ; e l s e i f ( ! g [ u ] [ PEO[ k ] ] ) return 0 ;
f o r ( k=0;k<n ; k++) i f ( ! mk [ k ] && g [ j ] [ k ] ) d e g r e e [ k]++;
}
return 1 ;
}

21
2.13 DFS — Bridge
int n , g [ maxn ] [ maxn ] , mk [ maxn ] , d [ maxn ] , low [ maxn ] ;
int c o l o r , t i , bridgenum , b r i d g e u [ maxn ] , b r i d g e v [ maxn ] ;

void d f s v i s i t ( int u , int p )


{
int v , s =0, bBridge = 0 ; low [ u]=d [ u]=++ t i ; mk [ u]=− c o l o r ;
fo r ( v = 1 ; v<=n ; v++) i f ( g [ u ] [ v ] && v!=p )
i f (mk [ v ]==0){ d f s v i s i t ( v , u ) ; s++;
i f ( low [ v]< low [ u ] ) low [ u]= low [ v ] ;
i f ( low [ v]==d [ v ] ) {
b r i d g e u [ bridgenum ]=u ;
b r i d g e v [ bridgenum++]=v ;
}
} e l s e i f ( d [ v]< low [ u ] ) low [ u]=d [ v ] ;
mk [ u]= c o l o r ;
}

void d f s ( )
{
int i , j , k ; memset (mk, 0 , s i z e o f (mk ) ) ;
c o l o r=t i=bridgenum =0;
fo r ( i = 1 ; i<=n ; i ++) i f ( ! mk [ i ]){ ++ c o l o r ; d f s v i s i t ( i , 0 ) ; }
cout<<bridgenum<<e n d l ;
}

2.14 DFS — Cutvertex


int n , g [ maxn ] [ maxn ] , mk [ maxn ] , d [ maxn ] , low [ maxn ] ;
int c o l o r , t i , cutvertexnum , c u t v e r t e x l i s t [ maxn ] ;

void d f s v i s i t ( int u , int p )


{
int v , s =0, bVertex = 0 ; low [ u]=d [ u]=++ t i ; mk [ u]=− c o l o r ;
fo r ( v = 1 ; v<=n ; v++) i f ( g [ u ] [ v ] && v!=p )
i f (mk [ v ]==0){ d f s v i s i t ( v , u ) ; s++;
i f ( low [ v]< low [ u ] ) low [ u]= low [ v ] ;
i f ( low [ v]>=d [ u ] ) bVertex =1;
} e l s e i f ( d [ v]< low [ u ] ) low [ u]=d [ v ] ;
i f ( ( p && bVertex ) | | ( ! p && s > 1 ) ) c u t v e r t e x l i s t [ cutvertexnum++]=u ;
mk [ u]= c o l o r ;
}

void d f s ( )
{
int i , j , k ; memset (mk, 0 , s i z e o f (mk ) ) ;
c o l o r=t i=cutvertexnum =0;
fo r ( i = 1 ; i<=n ; i ++) i f ( ! mk [ i ]){ ++ c o l o r ; d f s v i s i t ( i , 0 ) ; }
cout<<cutvertexnum<<e n d l ;
fo r ( i =0; i <cutvertexnum ; i ++) cout<<c u t v e r t e x l i s t [ i ]<<” ” ; cout<<e n d l ;
}

22
2.15 DFS — Block
int n , g [ maxn ] [ maxn ] , mk [ maxn ] , d [ maxn ] , low [ maxn ] , l e n , que [ maxn ] ;
int c o l o r , t i , cutvertexnum , c u t v e r t e x l i s t [ maxn ] , blocknum ;

void d v s v i s i t ( int u , int p )


{
int v , s =0, bCutvertex = 0 ; low [ u]=d [ u]=++ t i ; mk [ u]=− c o l o r ; que[++ l e n ]=u ;
fo r ( v = 1 ; v<=n ; v++) i f ( g [ u ] [ v ] && v!=p )
i f (mk [ v ]==0){ d v s v i s i t ( v , u ) ; s++;
i f ( low [ v]< low [ u ] ) low [ u]= low [ v ] ;
i f ( low [ v]>=d [ u ] ) {
while ( que [ l e n ] ! = v ) cout<<que [ l e n −−]<<” ” ;
cout<<que [ l e n −−]<<” ”<<u<<e n d l ;
bCutvertex = 1 ; blocknum++;
}
} e l s e i f ( d [ v]< low [ u ] ) low [ u]=d [ v ] ;
i f ( ( p && bCutvertex ) | | ( ! p && s > 1 ) ) c u t v e r t e x l i s t [ cutvertexnum++]=u ;
mk [ u]= c o l o r ;
}

void d f s ( )
{
int i , j , k ; memset (mk, 0 , s i z e o f (mk ) ) ;
c o l o r=t i=cutvertexnum=blocknum =0;
fo r ( i = 1 ; i<=n ; i ++) i f ( ! mk [ i ] ) {
++c o l o r ; l e n = 0 ; d v s v i s i t ( i , 0 ) ;
i f ( l e n > 1 | | d [ i ]== t i ) {
while ( l e n >1) cout<<que [ l e n −−]<<” ” ;
cout<<i <<e n d l ; blocknum++;
}
}
cout<<” Block Number : ”<<blocknum<<e n d l ;
cout<<” C u t v e rt e x Number : ”<<cutvertexnum<<e n d l ;
fo r ( i =0; i <cutvertexnum ; i ++) cout<<c u t v e r t e x l i s t [ i ]<<” ” ;
cout<<endl<<e n d l ;
}

23
2.16 DFS — Topological Sort
int n , mk [ maxn ] , topo [ maxn ] , g [ maxn ] [ maxn ] , ps , topook ;

void d f s ( int u )
{
i f (mk [ u ] <0){ topook = 0 ; return ; } ; i f (mk [ u ] > 0 ) return ; e l s e mk [ u]= −1;
fo r ( int v = 1 ; topook && v<=n ; v++) i f ( g [ u ] [ v ] ) d f s ( v ) ;
topo [ ps−−]=u ; mk [ u ] = 1 ;
}

void t o p o s o r t ( )
{
int i , j , k ; topook = 1 ; ps=n ; memset (mk, 0 , s i z e o f (mk ) ) ;
fo r ( i =1; topook && i<=n ; i ++) i f ( ! mk [ i ] ) d f s ( i ) ;
}

int main ( )
{
int i ,m, u , v ;
while ( c i n >>n>>m, n && ! c i n . f a i l ( ) ) {
memset ( g , 0 , s i z e o f ( g ) ) ;
while (m−−){ c i n >>u>>v ; g [ u ] [ v ] = 1 ; } ; t o p o s o r t ( ) ;
f o r ( i =1; i <n ; i ++) cout<<topo [ i ]<<” ” ; cout<<topo [ n]<< e n d l ;
}
return 0 ;
}

2.17 Strongly Connected Component


int g [ maxn ] [ maxn ] , n , mk [ maxn ] , l i s t [ maxn ] , num ;

void back ( int v )


{
mk [ v ] = 1 ; cout<<v<<” ” ;
fo r ( int u = 1 ; u<=n ; u++) i f ( ! mk [ u ] && g [ u ] [ v ] ) back ( u ) ;
}

void d f s ( int u )
{
mk [ u ] = 1 ;
fo r ( int v = 1 ; v<=n ; v++) i f ( ! mk [ v ] && g [ u ] [ v ] ) d f s ( v ) ;
l i s t [ num−−]=u ;
}

int main ( )
{
int i , j , k , l ;
c i n >>n ; f o r ( i =1; i<=n ; i ++) for ( j =1; j<=n ; j ++) c i n >>g [ i ] [ j ] ;
memset (mk, 0 , s i z e o f (mk ) ) ; num=n ;
fo r ( i =1; i<=n ; i ++) i f ( ! mk [ i ] ) d f s ( i ) ;
memset (mk, 0 , s i z e o f (mk ) ) ;
fo r ( i =1; i<=n ; i ++) i f ( ! mk [ l i s t [ i ] ] ) { back ( l i s t [ i ] ) ; cout<<e n d l ; }
return 0 ;
}

24
Chapter 3

Number Theory

3.1 Greatest Common Divisor


void gcd ( int a , int b , int &d , int &x , int &y )
{
i f ( b==0 ){ d=a ; x = 1 ; y = 0 ; return ; }
gcd ( b , a%b , d , y , x ) ;
y −= x ∗ ( a /b ) ;
}

3.2 Chinese Remainder Theorem


extended euclid(a, b) = ax + by
int e x t e n d e d e u c l i d ( int a , int b , int &x , int &y )
{
i f ( b==0){ x=1,y = 0 ; return a ; } e l s e {
int r e s=e x t e n d e d e u c l i d ( b , a%b , x , y ) ;
int t=x ; x=y ; y=t −(a/b ) ∗ y ;
return r e s ;
}
}
ax ≡ b (mod n) , n > 0
void m o d u l a r l i n e a r e q u a t i o n s o l v e r ( int a , int b , int n )
{
int d , x , y , e , i ;
d=e x t e n d e d e u c l i d ( a , n , x , y ) ;
i f ( b%d ! = 0 ) cout<<”No answer ! ” ; e l s e {
e=x ∗ ( b/d)%n ; // x=e i s a b a s i c s o l u t i o n
f o r ( i =0; i <d ; i ++) cout <<(e+i ∗ ( n/d))%n<<e n d l ;
}
}
Given bi , wi , i = 0 · · · len − 1 which wi > 0 , i = 0 · · · len − 1 and (wi , wj ) = 1 , i 6= j
Find an x which satisfies: x ≡ bi (mod wi ), i = 0 · · · len − 1
int c h i n a ( int b [ ] , int w [ ] , int l e n )
{
int i , d , x , y , x ,m, n ;
x = 0 ; n = 1 ; f or ( i =0; i <l e n ; i ++) n∗=w [ i ] ;
fo r ( i =0; i <l e n ; i ++){
m=n/w [ i ] ;
d=e x t e n d e d e u c l i d (w[ i ] ,m, x , y ) ;
x=(x+y∗m∗b [ i ])%n ;
}
return ( n+x%n)%n ;
}

25
3.3 Prime Generator
#define maxn 1 0 0 0 0 0 0 0
#define maxp 1 0 0 0 0 0 0

char mk [ maxn ] ;
int prime [ maxp ] , pnum ;

void GenPrime ( int n )


{
int i , j , k ; pnum = 0 ; memset (mk , 0 , n +1);
fo r ( i =2,k = 4 ; i<=n ; i ++,k+=i+i −1) i f ( ! mk [ i ] )
{
prime [ pnum++] = i ;
i f ( k<=n ) for ( j=i+i ; j<=n ; j+=i ) mk [ j ] = 1 ;
}
}

3.4 φ Generator
φ(n) = n p|n (1 − p1 ), where p is a prime.
Q

φ(846720) = 193536
int Phi ( int n ) // O( S q r t (N) )
{
int i , j , r e t=n ;
fo r ( i =2, j = 4 ; j<=n ; i ++, j+=i+i −1) i f ( ! ( n%i ) )
{
r e t = r e t / i ∗ ( i −1);
while ( ! ( n%i ) ) n/= i ;
}
i f ( n > 1 ) r e t = r e t / n ∗ ( n −1);
return r e t ;
}

#define maxn 1 0 0 0 0 0 0 0
#define maxp 1 0 0 0 0 0 0

int p h i [ maxn ] , prime [ maxp ] , pnum ;

void GenPhi ( int n ) // O( N l o g l o g N )


{
int i , j , k ; pnum = 0 ;
memset ( phi , 0 , ( n+1)∗ s i z e o f ( p h i [ 0 ] ) ) ;
phi [ 1 ] = 1 ;
fo r ( i = 2 ; i<=n ; i ++) i f ( ! p h i [ i ] )
{
prime [ pnum++] = i ;
f o r ( j=i ; j<=n ; j+=i )
{
i f ( ! p h i [ j ] ) p h i [ j ]= j ;
p h i [ j ] = p h i [ j ] / i ∗ ( i −1);
}
}
}

26
3.5 Discrete Logarithm
#define l l o n g int64
i n l i n e int mod( int x , int n ) { return ( x%n+n)%n ; }
// ax ≡ 1 (mod n)
int Inv ( int a , int n )
{
int d , x , y ; Gcd ( a , n , d , x , y ) ;
i f ( d==1) return mod( x , n ) ; e l s e return −1;
}
// x ≡ ab (mod n), a, b >= 0
int ModPow( int a , int b , int n )
{
l l o n g d ( 1 ) , i ( 0 ) ; while ( b>=(( l l o n g )1<< i ) ) i ++;
fo r(−− i ; i >=0;−− i ) { d=d∗d%n ; i f ( b&(1<< i ) ) d=d∗ a%n ; }
return d ;
}
// ax ≡ b (mod n), n is prime!
int mexp [ 5 0 0 0 0 ] , i d [ 5 0 0 0 0 ] ;

bool logcmp ( const int &a , const int &b ) { return mexp [ a]<mexp [ b ] ; }

int ModLog ( int a , int b , int n )


{
int i , j ,m = ( int ) c e i l ( s q r t ( n ) ) , i n v = Inv (ModPow( a ,m, n ) , n ) ;
fo r ( i d [ 0 ] = 0 , mexp [ 0 ] = i =1; i <m; i ++)
{ i d [ i ]= i ; mexp [ i ] = ( mexp [ i −1]∗( l l o n g ) a)%n ; }
s t d : : s t a b l e s o r t ( id , i d+m, logcmp ) ;
s t d : : s o r t ( mexp , mexp+m) ;
fo r ( i = 0 ; i <m; i ++) { // i ∗m < n
j = s t d : : lower bound ( mexp , mexp+m, b)−mexp ;
i f ( j <m && mexp [ j ]==b ) return i ∗m+i d [ j ] ;
b = ( b ∗ ( l l o n g ) i n v )%n ;
}
return −1;
}

27
3.6 Square Roots in Zp

#define l l o n g int64

int ModPow( int a , int b , int n ) // aˆ b mod n a , b>=0


{
llong d(1) , i (0);
while ( b>=(( l l o n g )1<< i ) ) i ++;
fo r (−− i ; i >=0;−− i ) { d=d∗d%n ; i f ( b&(1<< i ) ) d=d∗a%n ; }
return d ;
}

// x ∗ x = a ( mod n ) n s h o u l d be a prime and gcd ( a , n)==1


int ModSqrt ( int a , int n )
{
int b , k , i , x ;
i f ( n==2) return a%n ;
i f ( ModPow( a , ( n −1)/2 , n)==1) {
i f ( n%4==3) x = ModPow( a , ( n +1)/4 , n ) ; e l s e {
f o r ( b = 1 ; ModPow( b , ( n −1)/2 , n)==1; b++);
i =(n − 1 ) / 2 ; k = 0 ; do { i / = 2 ; k /=2;
i f ( ( ModPow( a , i , n ) ∗ ( l l o n g )ModPow( b , k , n)+1)%n==0) k+=(n −1)/2;
} while ( i %2==0);
x =( ModPow( a , ( i +1)/2 , n ) ∗ ( l l o n g )ModPow( b , k / 2 , n ) ) % n ;
} i f ( x∗2>n ) x=n−x ; return x ;
} return −1;
}

int main ( )
{
int a , n , c a s e c , x ; c i n >> c a s e c ;
while ( c a s e c −−) {
c i n >> a >> n ; x = ModSqrt ( a , n ) ;
i f ( x <0) c o u t << ”No r o o t ” << e n d l ;
e l s e i f ( x∗2==n ) c o u t << x << e n d l ;
e l s e c o u t << x << ’ ’ << n−x << e n d l ;
}
return 0 ;
}

28
Chapter 4

Algebraic Algorithms

4.1 Linear Equations in Z2


L
// Gauss Elimination : 0≤j<nn ai,j xi,j = ai,nn
int m, nn , num , l i s t [ maxn ] ; char a [ maxn ] [ maxn ] ;

int r e d u c e ( )
{
int i , j , k , r ;
fo r ( i=r = 0 ; i <nn ; i ++){
f o r ( j=r ; j <m && ! a [ j ] [ i ] ; j ++); i f ( j>=m) continue ;
i f ( j >r ) for ( k=0;k<=nn ; k++) s t d : : swap ( a [ r ] [ k ] , a [ j ] [ k ] ) ;
f o r (num=0,k=i ; k<=nn ; k++) i f ( a [ r ] [ k ] ) l i s t [ num++]=k ;
f o r ( j =0; j <m; j ++) i f ( j != r && a [ j ] [ i ] )
f o r ( k=0;k<num ; k++) a [ j ] [ l i s t [ k ] ] ˆ = 1 ;
++r ;
}
fo r ( i =0; i <m; i ++)
i f ( a [ i ] [ nn ] ) {
f o r ( j =0; j <nn && ! a [ i ] [ j ] ; j ++);
i f ( j==nn ) return 0 ; // e l s e x [ j ]=a [ i ] [ nn ] / a [ i ] [ j ] ;
}
return 1 ;
}

29
4.2 Linear Equations in Z
P
// Gauss Elimination : 0≤j<nn ai,j xi,j = ai,nn
int m, nn , a [ maxn ] [ maxn ] ;

int gcd ( int x , int y )


{ i f ( y==0) return x ; e l s e return gcd ( y , x%y ) ; }

void y u e f e n ( int b [ ] , int c t )


{
int i , j =0,k ;
fo r ( i =0; i <c t ; i ++) i f ( b [ i ] ) i f ( j ) k=gcd ( b [ i ] , k ) ; e l s e { k=b [ i ] ; j =1;}
i f ( k ! = 0 ) f o r ( i =0; i <c t ; i ++) b [ i ]/=k ;
}

int r e d u c e ( ) // r e t u r n 0 means no s o l u t i o n !
{
int i , j , k , r , tmp ;
fo r ( i=r = 0 ; i <nn ; i ++){
f o r ( j=r ; j <m && ! a [ j ] [ i ] ; j ++); i f ( j>=m) continue ;
i f ( j >r ) for ( k=0;k<=nn ; k++) s t d : : swap ( a [ r ] [ k ] , a [ j ] [ k ] ) ;
f o r ( j =0; j <m; j ++) i f ( j != r && a [ j ] [ i ] ) {
tmp=a [ j ] [ i ] ;
f o r ( k=0;k<=nn ; k++) a [ j ] [ k]=a [ j ] [ k ] ∗ a [ r ] [ i ]−tmp∗ a [ r ] [ k ] ;
y u e f e n ( a [ j ] , nn +1);
} ++ r ;
}
fo r ( i =0; i <m; i ++) i f ( a [ i ] [ nn ] ) {
f o r ( j =0; j <nn && ! a [ i ] [ j ] ; j ++);
i f ( j==nn ) return 0 ; // e l s e x [ j ]=a [ i ] [ nn ] / a [ i ] [ j ] ;
}
return 1 ;
}

4.3 Linear Equations in Q


Note: fraction.h contains a Fraction Class (Section 1.4 on Page 8)
#include<f r a c t i o n . h>

int m, nn ; F r a c t i o n a [ maxn ] [ maxn ] ;


int dcmp ( F r a c t i o n x ) { return x . a ; }

int r e d u c e ( )
{
int i , j , k , r ; double tmp ;
fo r ( i=r = 0 ; i <nn ; i ++){
f o r ( j=r ; j <m && !dcmp ( a [ j ] [ i ] ) ; j ++); i f ( j>=m) continue ;
i f ( j >r ) for ( k=0;k<=nn ; k++) s t d : : swap ( a [ r ] [ k ] , a [ j ] [ k ] ) ;
f o r ( j =0; j <m; j ++) i f ( j != r && dcmp ( a [ j ] [ i ] ) ) {
tmp=a [ j ] [ i ] / a [ r ] [ i ] ;
f o r ( k=0;k<=nn ; k++) a [ j ] [ k]=a [ j ] [ k]−tmp∗ a [ r ] [ k ] ;
} ++ r ;
}
fo r ( i =0; i <m; i ++) i f ( dcmp ( a [ i ] [ nn ] ) ) {
f o r ( j =0; j <nn && !dcmp ( a [ i ] [ j ] ) ; j ++);
i f ( j==nn ) return 0 ; // e l s e x [ j ]=a [ i ] [ nn ] / a [ i ] [ j ] ;
} return 1 ;
}

30
4.4 Linear Equations in R
const double e p s=1e −8;
int m, nn ; double a [ maxn ] [ maxn ] ;

int dcmp ( double x ) { i f ( x>e p s ) return 1 ; i f ( x<−e p s ) return − 1 ; return 0 ; }

int r e d u c e ( ) // r i s rank
{
int i , j , k , r ; double tmp ;
fo r ( i=r = 0 ; i <nn ; i ++){
f o r ( j=r ; j <m && !dcmp ( a [ j ] [ i ] ) ; j ++); i f ( j>=m) continue ;
i f ( j >r ) for ( k=0;k<=nn ; k++) s t d : : swap ( a [ r ] [ k ] , a [ j ] [ k ] ) ;
f o r ( j =0; j <m; j ++) i f ( j != r && dcmp ( a [ j ] [ i ] ) ) {
tmp=a [ j ] [ i ] / a [ r ] [ i ] ;
f o r ( k=0;k<=nn ; k++) a [ j ] [ k]−=tmp∗a [ r ] [ k ] ;
} ++ r ;
}
fo r ( i =0; i <m; i ++) i f ( dcmp ( a [ i ] [ nn ] ) ) {
f o r ( j =0; j <nn && !dcmp ( a [ i ] [ j ] ) ; j ++);
i f ( j==nn ) return 0 ; // e l s e x [ j ]=a [ i ] [ nn ] / a [ i ] [ j ] ;
} return 1 ;
}

4.5 Roots of Polynomial


Pn d
Find the roots of fa (x) = i=0 ai xi using Newton Iterations, fb (x) = fa (x) dx
const double e p s=1e −5;
#define genx ( rand ( ) % 1 0 0 0 ) / 1 0 0 . 0

int dcmp ( double x )


{ i f ( x>e p s ) return 1 ; e l s e i f ( x<−e p s ) return − 1 ; e l s e return 0 ; }

double f ( double a [ ] , int n , double x )


{
double r e t =0,xx =1;
fo r ( int i =0; i<=n ; i ++){ r e t+=a [ i ] ∗ xx ; xx∗=x ; }
return r e t ;
}

double newton ( double a [ ] , double b [ ] , int n )


{
double dy , y , x=genx , l a s t x=x −1;
while ( y=f ( a , n , x ) , dcmp ( l a s t x −x ) ) {
l a s t x=x ; dy=f ( b , n−1,x ) ;
i f ( ! dcmp ( dy ) ) x=genx ; e l s e x=x−y/dy ;
}
return x ;
}

void s o l v e ( double a [ ] , double x [ ] , int n )


{
int i , j ; double b [ maxn ] ;
fo r ( j=n ; j >0; j −−){
f o r ( i =0; i <j ; i ++) b [ i ]=a [ i +1]∗( i +1);
x [ j −1]=newton ( a , b , j ) ;
f o r ( b [ j ] = 0 , i=j − 1 ; i >=0; i −−) b [ i ]=a [ i +1]+b [ i +1]∗ x [ j − 1 ] ;
f o r ( i =0; i <j ; i ++) a [ i ]=b [ i ] ;
}
}

31
4.6 Roots of Cubic and Quartic

c0 + c1 ∗ x + c2 ∗ x2 + c3 ∗ x3 + c4 ∗ x4 = 0

The functions return the number of distinct non-complex roots and put the values into the s array.
const double p i = a c o s ( − 1 . 0 ) ; // 3.141 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6

double c b r t ( double x )
{
i f ( x> e p s ) return pow ( x , 1 / 3 . 0 ) ;
i f ( x<−e p s ) return −pow( −x , 1 / 3 . 0 ) ;
return 0 ;
}

int S o l v e Q u a d r i c ( double c [ 3 ] , double s [ 2 ] )


{
double p , q , d ; // normal form : x ˆ2 + px + q = 0
p = c [ 1 ] / ( 2 ∗ c [ 2 ] ) ; q = c [ 0 ] / c [ 2 ] ; d = p∗p−q ;
i f ( dcmp ( d ) = = 0 ) { s [ 0 ] = − p ; return 1 ; }
i f ( dcmp ( d ) < 0 ) return 0 ;
d = sqrt ( d ) ;
s [0] = − p + d ;
s [1] = − p − d ;
return 2 ;
}

int S o l v e C u b i c ( double c [ 4 ] , double s [ 3 ] )


{
int i , num ; // normal form : x ˆ3 + Axˆ2 + Bx + C = 0
double sub , A, B , C , sqa , p , q , cbp , d ;
A = c [2]/ c [ 3 ] ; B = c [1]/ c [ 3 ] ; C = c [0]/ c [3];
sqa = A ∗ A ; // x = y − A/ 3 => x ˆ3 + px + q = 0
p = 1 . 0 / 3 ∗ ( − 1 . 0 / 3 ∗ sqa + B ) ;
q = 1 . 0 / 2 ∗ ( 2 . 0 / 2 7 ∗ A ∗ sqa − 1 . 0 / 3 ∗ A ∗ B + C ) ;
cbp = p ∗ p ∗ p ; // use Cardano ’ s f o r m u l a
d = q ∗ q + cbp ;
i f ( dcmp ( d )==0 ) {
i f ( dcmp ( q ) = = 0 ) { s [ 0 ] = 0 ; num = 1 ; } // one t r i p l e s o l u t i o n
e l s e { // one s i n g l e and one d o u b l e s o l u t i o n
double u = c b r t ( −q ) ;
s [ 0 ] = 2 ∗ u ; s [ 1 ] = − u ; num = 2 ;
}
} e l s e i f ( dcmp ( d ) < 0 ) { // Casus i r r e d u c i b i l i s : t h r e e r e a l s o l u t i o n s
double p h i = 1 . 0 / 3 ∗ a c o s (−q / s q r t (−cbp ) ) ;
double t = 2 ∗ s q r t (−p ) ;
s[ 0 ] = t ∗ cos ( phi ) ;
s [ 1 ] = − t ∗ cos ( phi + pi / 3 ) ;
s [ 2 ] = − t ∗ cos ( phi − pi / 3 ) ;
num = 3 ;
} e l s e { /∗ one r e a l s o l u t i o n ∗/
d = s q r t ( d ) ; double u = c b r t ( d−q ) , v = − c b r t ( d+q ) ;
s [ 0 ] = u + v ; num = 1 ;
}
/∗ r e s u b s t i t u t e ∗/
sub = 1 . 0 / 3 ∗ A ; for ( i = 0 ; i <num; ++ i ) s [ i ] −= sub ;
return num ;
}

32
int S o l v e Q u a r t i c ( double c [ 5 ] , double s [ 4 ] )
{
double e [ 4 ] , z , u , v , sub , A, B , C , d , sqa , p , q , r ;
int i , num ; // x ˆ4 + Axˆ3 + Bxˆ2 + Cx + D = 0
A = c [3]/ c [ 4 ] ; B = c [2]/ c [ 4 ] ; C = c [1]/ c [ 4 ] ; d = c [0]/ c [4];
sqa = A ∗ A ; // x = y − A/ 4 => x ˆ4 + px ˆ2 + qx + r = 0
p = − 3 . 0 / 8 ∗ sqa + B ;
q = 1 . 0 / 8 ∗ sqa ∗ A − 1 . 0 / 2 ∗ A ∗ B + C ;
r = − 3.0/256∗ sqa ∗ sqa + 1 . 0 / 1 6 ∗ sqa ∗B − 1 . 0 / 4 ∗A∗C + d ;
i f ( dcmp ( r ) = = 0 ) { // no a b s o l u t e term : y ( y ˆ3 + py + q ) = 0
e [0] = q ; e [1] = p ; e [2] = 0; e [3] = 1;
num = S o l v e C u b i c ( e , s ) ; s [ num+ + ] = 0 ;
} else { // s o l v e t h e r e s o l v e n t c u b i c . . .
e [0] = 1.0/2 ∗ r ∗ p − 1.0/8 ∗ q ∗ q ; e [1] = − r ;
e [2] = − 1.0/2 ∗ p ; e [3] = 1;
SolveCubic ( e , s ) ;
z = s [ 0 ]; // . . . and t a k e t h e one r e a l s o l u t i o n
u = z ∗ z−r ; v = 2∗ z−p ; // . . . t o b u i l d two q u a d r i c e q u a t i o n s
i f ( dcmp ( u)==0) u = 0 ; e l s e i f ( dcmp ( u ) >0) u=s q r t ( u ) ; e l s e return 0 ;
i f ( dcmp ( v)==0) v = 0 ; e l s e i f ( dcmp ( v ) >0) v=s q r t ( v ) ; e l s e return 0 ;
e [ 0 ] = z−u ; e [ 1 ] = dcmp ( q) <0 ? −v : v ; e [ 2 ] = 1 ;
num = S o l v e Q u a d r i c ( e , s ) ;
e [ 0 ] = z+u ; e [ 1 ] = dcmp ( q ) <0 ? v : − v ; e [ 2 ] = 1 ;
num += S o l v e Q u a d r i c ( e , s + num ) ;
}
sub = 1 . 0 / 4 ∗A ; for ( i = 0 ; i <num; ++ i ) s [ i ] −= sub ; // r e s u b s t i t u t e
return num ;
}

4.7 Fast Fourier Transform


const double e p s=1e −8;
const double p i=a c o s ( − 1 . 0 ) ;

#define cp complex<double>

i n l i n e int max( int a , int b ) { i f ( a>b ) return a ; e l s e return b ; }


i n l i n e int dcmp ( double a ) { i f ( a<−e p s ) return − 1 ; return ( a>e p s ) ; }

void f f t ( cp ∗ x , int n , cp ∗ y , int bInv ) // y=Wx, w [ j , k ]= e ˆ i j k


{
i f ( n==1) { y [ 0 ] = x [ 0 ] ; return ; }
cp ∗ xeven = new cp [ n / 2 ] , ∗ xodd = new cp [ n / 2 ] , w( 1 , 0 ) ,
∗ yeven = new cp [ n / 2 ] , ∗ yodd = new cp [ n / 2 ] , wn ; int i ;
i f ( bInv ) wn=cp ( c o s (−2∗ p i /n ) , s i n (−2∗ p i /n ) ) ;
e l s e wn=cp ( c o s ( 2 ∗ p i /n ) , s i n ( 2 ∗ p i /n ) ) ;
fo r ( i = 0 ; i <n / 2 ; i ++)
{
xeven [ i ] = x [ i ∗ 2 ] ;
xodd [ i ] = x [ i ∗ 2 + 1 ] ;
}
f f t ( xeven , n / 2 , yeven , bInv ) ;
f f t ( xodd , n / 2 , yodd , bInv ) ;
fo r ( i = 0 ; i <n / 2 ; i ++)
{
y[ i ] = yeven [ i ] + w∗ yodd [ i ] ;
y [ i+n / 2 ] = yeven [ i ] − w∗ yodd [ i ] ;
w ∗= wn ;
}
delete xeven ; delete yeven ; delete xodd ; delete yodd ;
}

33
4.8 FFT - Polynomial Multiplication
void Po ly Mu lt i ( double ∗ a , int na , double ∗ b , int nb , double ∗ c , int &nc )
{
int i , j , n=(na>nb ) ? na : nb ;
n=1<<((int ) c e i l ( l o g ( 2 ∗ n ) / l o g (2) − e p s ) ) ;
cp ∗ x=new cp [ n ] , ∗ ya=new cp [ n ] , ∗ yb=new cp [ n ] , ∗ yc=new cp [ n ] ;
fo r ( i =0; i <n ; i ++) x [ i ]=( i <na ) ? a [ i ] : 0 ; f f t ( x , n , ya , 0 ) ;
fo r ( i =0; i <n ; i ++) x [ i ]=( i <nb ) ? b [ i ] : 0 ; f f t ( x , n , yb , 0 ) ;
fo r ( i =0; i <n ; i ++) yc [ i ]= ya [ i ] ∗ yb [ i ] ; f f t ( yc , n , x , 1 ) ;
fo r ( i =0; i <n ; i ++) c [ i ]=x [ i ] . r e a l ( ) / n ;
fo r ( nc=n ; nc >0 && dcmp ( c [ nc −1])==0; nc −−);
delete x ; delete ya ; delete yb ; delete yc ;
}

4.9 FFT - Convolution


Pn−1
rk = i=0 a[i] ∗ b[i − k]
void C o n v o l u t i o n 1 ( int ∗ a , int ∗ b , int ∗ c , int n )
{
int m, i , j , ∗ rb=new int [ n ] ; rb [ 0 ] = b [ 0 ] ;
fo r ( i =1; i <n ; i ++) rb [ i ]=b [ n−i ] ;
Po l yMu lt i1 ( a , n , rb , n , c ,m) ;
fo r ( i =0; i <n ; i ++) c [ i ]+=c [ i+n ] ;
delete [ ] rb ;
}

\ \ N must be power o f 2
void C o n v o l u t i o n 2 ( int ∗ a , int ∗ b , int ∗ c , int n )
{
int i , j ;
cp ∗ x=new cp [ n ] , ∗ ya=new cp [ n ] , ∗ yb=new cp [ n ] , ∗ yc=new cp [ n ] ;
x [0]=b [ 0 ] ;
fo r ( i =1; i <n ; i ++) x [ i ]=( i <n ) ? b [ n−i ] : 0 ; f f t ( x , n , yb , 0 ) ;
fo r ( i =0; i <n ; i ++) x [ i ]=( i <n ) ? a [ i ]:0; f f t ( x , n , ya , 0 ) ;
fo r ( i =0; i <n ; i ++) yc [ i ]= ya [ i ] ∗ yb [ i ] ; f f t ( yc , n , x , 1 ) ;
fo r ( i =0; i <n ; i ++) c [ i ]= int ( x [ i ] . r e a l ( ) / n + 0 . 5 ) ;
delete x ; delete ya ; delete yb ; delete yc ;
}

4.10 FFT - Reverse Bits


#define f o r i f ( 0 ) ; e l s e f or
const double p i = a c o s ( − 1 . 0 ) ;
const int MFB = 1 6 ;
int ∗ ∗ bt = 0 ;

struct cp { double re , im ; } ;

i n l i n e int R e v e r s e B i t s ( int index , int bitnum ) {


int r e t = 0 ;
fo r ( int i = 0 ; i <bitnum ; ++ i , i n d e x >>= 1)
r e t = ( r e t < < 1) | ( index & 1 ) ;
return r e t ;
}

34
void InitFFT ( ) {
bt = new int ∗ [MFB ] ; int i , j , l e n g t h ;
fo r ( i =1 , l e n g t h = 2 ; i<=MFB; ++ i , l e n g t h <<=1) {
bt [ i −1] = new int [ l e n g t h ] ;
f o r ( j = 0 ; j <l e n g t h ; ++ j ) bt [ i − 1 ] [ j ] = R e v e r s e B i t s ( j , i ) ;
}
}

i n l i n e int FRB( int i , int bitnum ) {


return bitnum <= MFB ? bt [ bitnum − 1 ] [ i ] : R e v e r s e B i t s ( i , bitnum ) ;
}

void FFT( cp ∗ in , cp ∗ out , int n , bool bInv )


{
int i , j , k , ed , l e n , bitnum = 0 ; i f ( ! bt ) InitFFT ( ) ;
while ( !((1 < < bitnum)&n ) ) bitnum++;
fo r ( i = 0 ; i <n; ++ i ) out [FRB( i , bitnum ) ] = i n [ i ] ;
double b a s i c a n g l e = p i ∗ ( bInv ? − 2 : 2 ) ;
cp a0 , a1 , a2 , a , b ;
fo r ( ed = 1 , l e n = 2 ; l e n <= n ; l e n < <= 1) {
double d e l t a a n g l e = b a s i c a n g l e / l e n ;
double s i n 1 = s i n (− d e l t a a n g l e ) , s i n 2 = s i n (− d e l t a a n g l e ∗ 2 ) ;
double c o s 1 = c o s (− d e l t a a n g l e ) , c o s 2 = c o s (− d e l t a a n g l e ∗ 2 ) ;
f o r ( i = 0 ; i <n ; i+=l e n ) {
a1 . r e=c o s 1 ; a1 . im=s i n 1 ; a2 . r e=c o s 2 ; a2 . im=s i n 2 ;
f o r ( j=i , k = 0 ; k<ed ; ++ j , ++k ) {
a0 . r e =2∗ c o s 1 ∗ a1 . re−a2 . r e ; a0 . im=2∗ c o s 1 ∗ a1 . im−a2 . im ;
a2 = a1 ; a1 = a0 ; b=out [ j+ed ] ;
a . r e = a0 . r e ∗b . r e − a0 . im∗b . im ;
a . im = a0 . im∗b . r e + a0 . r e ∗b . im ;
out [ j+ed ] . r e=out [ j ] . re−a . r e ;
out [ j+ed ] . im=out [ j ] . im−a . im ;
out [ j ] . r e+=a . r e ;
out [ j ] . im+=a . im ;
}
}
ed = l e n ;
}
i f ( bInv ) f or ( int i = 0 ; i < n; ++ i ) { out [ i ] . r e /= n ; out [ i ] . im/=n ; }
}

// n must be power o f 2
void c o n v o l u t i o n ( double ∗ a , double ∗ b , double ∗ r , int n ) {
int i ;
cp ∗ s=new cp [ n ] , ∗ d1=new cp [ n ] , ∗ d2=new cp [ n ] , ∗ y=new cp [ n ] ;
s [ 0 ] . im=b [ 0 ] ; s [ 0 ] . r e =0;
fo r ( i = 1 ; i <n; ++ i ) s [ i ] . r e=b [ n−i ] , s [ i ] . im = 0 ; FFT( s , d2 , n , f a l s e ) ;
fo r ( i = 0 ; i <n; ++ i ) s [ i ] . r e=a [ i ] , s [ i ] . im = 0 ; FFT( s , d1 , n , f a l s e ) ;
fo r ( i = 0 ; i <n; ++ i ) {
y [ i ] . r e = d1 [ i ] . r e ∗d2 [ i ] . r e − d1 [ i ] . im∗d2 [ i ] . im ;
y [ i ] . im = d1 [ i ] . r e ∗d2 [ i ] . im + d1 [ i ] . im∗d2 [ i ] . r e ;
}
FFT( y , s , n , true ) ;
fo r ( i = 0 ; i <n; ++ i ) r [ i ] = s [ i ] . r e ;
delete s ; delete d1 ; delete d2 ; delete y ;
}

35
4.11 Linear Programming - Primal Simplex
Primal Simplex Method for solving Linear Programming problem in Standard Form
maximize
c1 x1 + c2 x2 + · · · + cn xn + ans
subject to

a1,1 x1 + a1,2 x2 + · · · + a1,n xn ≤ rhs1


a2,1 x1 + a2,2 x2 + · · · + a2,n xn ≤ rhs2
..
.
am,1 x1 + am,2 x2 + · · · + am,n xn ≤ rhsm

const double e p s = 1 e −8;


const double i n f = 1 e15 ;

#define OPTIMAL −1
#define UNBOUNDED −2
#define FEASIBLE −3
#define INFEASIBLE −4
#define PIVOT OK 1

int b a s i c [ maxn ] , row [ maxm ] , c o l [ maxn ] ;


double c0 [ maxn ] ;

double dcmp ( double x )


{
i f ( x > e p s ) return 1 ;
i f ( x < − e p s ) return −1;
return 0 ;
}

int P i v o t ( int n , int m, double ∗ c , double a [ maxn ] [ maxn ] ,


double ∗ rhs , int & i , int & j )
{
double min = i n f ; int k = −1;
fo r ( j = 0 ; j<=n ; j ++) i f ( ! b a s i c [ j ] && dcmp ( c [ j ] ) > 0 )
i f ( k < 0 | | dcmp ( c [ j ]− c [ k ] ) > 0 ) k=j ;
j=k ; i f ( k < 0 ) return OPTIMAL;
fo r ( k=−1, i = 1 ; i<=m; i ++) i f ( dcmp ( a [ i ] [ j ] ) > 0 )
i f ( dcmp ( r h s [ i ] / a [ i ] [ j ]−min ) < 0 ) { min = r h s [ i ] / a [ i ] [ j ] ; k=i ; }
i=k ; i f ( k < 0 ) return UNBOUNDED; e l s e return PIVOT OK ;
}

int P h a s e I I ( int n , int m, double ∗ c , double a [ maxn ] [ maxn ] ,


double ∗ rhs , double &ans , int P i v o t I n d e x )
{
int i , j , k , l ; double tmp ;
while ( k=P i v o t ( n ,m, c , a , rhs , i , j ) , k==PIVOT OK | | P i v o t I n d e x )
{
i f ( P i v o t I n d e x ) { j = 0 ; i=P i v o t I n d e x ; P i v o t I n d e x = 0 ; }
b a s i c [ row [ i ] ] = 0 ; c o l [ row [ i ] ] = 0 ; b a s i c [ j ] = 1 ; c o l [ j ]= i ; row [ i ]= j ;
tmp=a [ i ] [ j ] ; for ( k=0;k<=n ; k++) a [ i ] [ k]/=tmp ; r h s [ i ]/=tmp ;
f o r ( k=1;k<=m; k++) i f ( k!= i && dcmp ( a [ k ] [ j ] ) )
{
tmp = −a [ k ] [ j ] ; for ( l =0; l<=n ; l ++) a [ k ] [ l ]+=tmp∗ a [ i ] [ l ] ;
r h s [ k ] += tmp∗ r h s [ i ] ;
}
tmp=−c [ j ] ; for ( l =0; l<=n ; l ++) c [ l ]+=a [ i ] [ l ] ∗ tmp ; ans−=tmp∗ r h s [ i ] ;
}
return k ;
}
36
int PhaseI ( int n , int m, double ∗ c , double a [ maxn ] [ maxn ] , double ∗ rhs , double & ans )
{
int i , j , k = −1; double tmp , min = 0 , ans0 = 0 ;
fo r ( i = 1 ; i<=m; i ++) i f ( dcmp ( r h s [ i ]−min ) < 0 ) { min=r h s [ i ] ; k=i ; }
i f ( k < 0 ) return FEASIBLE ;
fo r ( i = 1 ; i<=m; i ++) a [ i ] [ 0 ] = − 1 ;
fo r ( j = 1 ; j<=n ; j ++) c0 [ j ] = 0 ; c0 [ 0 ] = − 1 ;
P h a s e I I ( n , m, c0 , a , rhs , ans0 , k ) ;
i f ( dcmp ( ans0 ) < 0 ) return INFEASIBLE ;
fo r ( i = 1 ; i<=m; i ++) a [ i ] [ 0 ] = 0 ;
fo r ( j = 1 ; j<=n ; j ++) i f ( dcmp ( c [ j ] ) & & b a s i c [ j ] )
{
tmp = c [ j ] ; ans += r h s [ c o l [ j ] ] ∗ tmp ;
f o r ( i = 0 ; i<=n ; i ++) c [ i ] −= tmp∗ a [ c o l [ j ] ] [ i ] ;
}
return FEASIBLE ;
}

int s i m p l e x ( int n , int m, double ∗ c , double a [ maxn ] [ maxn ] ,


double ∗ rhs , double &ans , double ∗ x ) // s t a n d a r d form
{
int i , j , k ;
fo r ( i = 1 ; i<=m; i ++)
{
f o r ( j=n + 1 ; j<=n+m; j ++) a [ i ] [ j ] = 0 ;
a [ i ] [ n+i ] = 1 ; a [ i ] [ 0 ] = 0 ;
row [ i ] = n+i ; c o l [ n+i ] = i ;
}
k = PhaseI ( n+m, m, c , a , rhs , ans ) ;
i f ( k == INFEASIBLE ) return k ;
k = P h a s e I I ( n+m, m, c , a , rhs , ans , 0 ) ;
fo r ( j =0; j<=n+m; j ++) x [ j ] = 0 ;
fo r ( i =1; i<=m; i ++) x [ row [ i ] ] = r h s [ i ] ;
return k ;
}

int n , m; double c [ maxn ] , ans , a [ maxm ] [ maxn ] , r h s [ maxm ] , x [ maxn ] ;

int main ( )
{
ifstream cin (” lp . in ” ) ;
int i , j ;
while ( c i n >>n>>m && ! c i n . f a i l ( ) )
{
f o r ( j = 1 ; j<=n ; j ++) c i n >>c [ j ] ; c i n >>ans ; c [0]=0;
f o r ( i = 1 ; i<=m; i ++){ for ( j = 1 ; j<=n ; j ++) c i n >>a [ i ] [ j ] ; c i n >>r h s [ i ] ; }
switch ( s i m p l e x ( n , m, c , a , rhs , ans , x ) )
{
case OPTIMAL :
p r i n t f ( ”OPTIMAL\n%10 l f \n” , ans ) ;
for ( j =1; j<=n ; j ++) p r i n t f ( ”x [ %2d ] = %10 l f \n” , j , x [ j ] ) ;
break ;
case UNBOUNDED :
p r i n t f ( ”UNBOUNDED\n” ) ; break ;
case INFEASIBLE :
p r i n t f ( ”INFEASIBLE\n” ) ; break ;
} p r i n t f ( ” \n” ) ;
}
return 0 ;
}

37
Chapter 5

Computational Geometry

5.1 Basic Operations


const double e p s = 1 e −8;
const double p i = a c o s ( − 1 . 0 ) ;

struct CPoint { double x , y ; } ;

double min ( double x , double y ) { i f ( x<y ) return x ; e l s e return y ; }

double max( double x , double y ) { i f ( x>y ) return x ; e l s e return y ; }

double s q r ( double x ) { return x∗x ; }

int dcmp ( double x )


{
i f ( x<−e p s ) return − 1 ; e l s e return ( x>e p s ) ;
}

double c r o s s ( CPoint p0 , CPoint p1 , CPoint p2 )


{
return ( p1 . x−p0 . x ) ∗ ( p2 . y−p0 . y)−(p2 . x−p0 . x ) ∗ ( p1 . y−p0 . y ) ;
}

double dot ( CPoint p0 , CPoint p1 , CPoint p2 )


{
return ( p1 . x−p0 . x ) ∗ ( p2 . x−p0 . x)+( p1 . y−p0 . y ) ∗ ( p2 . y−p0 . y ) ;
}

double d i s s q r ( CPoint p1 , CPoint p2 )


{
return s q r ( p1 . x−p2 . x)+ s q r ( p1 . y−p2 . y ) ;
}

double d i s ( CPoint p1 , CPoint p2 )


{
return s q r t ( s q r ( p1 . x−p2 . x)+ s q r ( p1 . y−p2 . y ) ) ;
}

int PointEqual ( const CPoint &p1 , const CPoint &p2 )


{
return dcmp ( p1 . x−p2 . x)==0 && dcmp ( p1 . y−p2 . y)==0;
}

38
5.2 Extended Operations
// C r o s s i n g Angle o f P0P1 −> P0P2 , range i n ( − pi , p i ]
double a n g l e ( CPoint p0 , CPoint p1 , CPoint p2 )
{
double c r = c r o s s ( p0 , p1 , p2 ) ;
double dt = dot ( p0 , p1 , p2 ) ;
i f ( dcmp ( c r )==0) c r = 0 . 0 ;
i f ( dcmp ( dt )==0) dt = 0 . 0 ;
return atan2 ( cr , dt ) ;
}

int PointOnLine ( CPoint p0 , CPoint p1 , CPoint p2 )


{
return dcmp ( c r o s s ( p0 , p1 , p2 ))==0;
}

int PointOnSegment ( CPoint p0 , CPoint p1 , CPoint p2 )


{
return dcmp ( c r o s s ( p0 , p1 , p2))==0 && dcmp ( dot ( p0 , p1 , p2 )) <=0;
}

// 1 = c r o s s ; 0 = parallel ; −1 = o v e r l a p
int L i n e I n t e r s e c t i o n ( CPoint p1 , CPoint p2 , CPoint p3 , CPoint p4 , CPoint &cp )
{
double u=c r o s s ( p1 , p2 , p3 ) , v=c r o s s ( p2 , p1 , p4 ) ;
i f ( dcmp ( u+v ) )
{
cp . x=(p3 . x∗v + p4 . x∗u ) / ( v+u ) ;
cp . y=(p3 . y∗v + p4 . y∗u ) / ( v+u ) ;
return 1 ;
}
i f ( dcmp ( u ) ) return 0 ; // e l s e u=v =0;
i f ( dcmp ( c r o s s ( p3 , p4 , p1 ) ) ) return 0 ;
return −1;
}

int S e g m e n t I n t e r s e c t i o n ( CPoint p1 , CPoint p2 , CPoint p3 , CPoint p4 , CPoint &cp )


{
int r e t=L i n e I n t e r s e c t i o n ( p1 , p2 , p3 , p4 , cp ) ;
i f ( r e t ==1) return PointOnSegment ( cp , p1 , p2 ) && PointOnSegment ( cp , p3 , p4 ) ;
i f ( r e t ==−1 && ( PointOnSegment ( p1 , p3 , p4 ) | | PointOnSegment ( p2 , p3 , p4 )
| | PointOnSegment ( p3 , p1 , p2 ) | | PointOnSegment ( p4 , p1 , p2 ) ) )
return −1;
return 0 ;
}

int S e g m e n t I n t e r s e c T e s t ( CPoint p1 , CPoint p2 , CPoint p3 , CPoint p4 )


{
i f ( max( p1 . x , p2 . x ) + e p s < min ( p3 . x , p4 . x ) | |
max( p3 . x , p4 . x ) + e p s < min ( p1 . x , p2 . x ) | |
max( p1 . y , p2 . y ) + e p s < min ( p3 . y , p4 . y ) | |
max( p3 . y , p4 . y ) + e p s < min ( p1 . y , p2 . y ) ) return 0 ;
int d1=dcmp ( c r o s s ( p3 , p4 , p2 ) ) ;
int d2=dcmp ( c r o s s ( p3 , p4 , p1 ) ) ;
int d3=dcmp ( c r o s s ( p1 , p2 , p4 ) ) ;
int d4=dcmp ( c r o s s ( p1 , p2 , p3 ) ) ;
i f ( d1∗d2 = = 1 | | d3∗d4 ==1 ) return 0 ;
i f ( d1==0 && d2==0 && d3==0 && d4 ==0 ) return −1;
return 1 ;
}

39
// 0 = o u t s i d e ; 1 = inside ; 2 = boundary
int P o i n t I n P o l y g o n ( CPoint cp , CPoint p [ ] , int n )
{
int i , k , d1 , d2 , wn=0;
double sum=0;
p [ n]=p [ 0 ] ;
fo r ( i =0; i <n ; i ++)
{
i f ( PointOnSegment ( cp , p [ i ] , p [ i + 1 ] ) ) return 2 ;
k = dcmp ( c r o s s ( p [ i ] , p [ i +1] , cp ) ) ;
d1 = dcmp ( p [ i + 0 ] . y − cp . y ) ;
d2 = dcmp ( p [ i + 1 ] . y − cp . y ) ;
i f ( k>0 && d1<=0 && d2 >0) wn++;
i f ( k<0 && d2<=0 && d1 >0) wn−−;
}
return wn! = 0 ;
}

double PointToLine ( CPoint p0 , CPoint p1 , CPoint p2 , CPoint &cp )


{
double d=d i s ( p1 , p2 ) ;
double s = c r o s s ( p1 , p2 , p0 ) / d ;
cp . x = p0 . x + s ∗ ( p2 . y−p1 . y ) / d ;
cp . y = p0 . y − s ∗ ( p2 . x−p1 . x ) / d ;
return s ; // ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S i g n e d Magnitude ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗
}

void P o i n t P r o j L i n e ( CPoint p0 , CPoint p1 , CPoint p2 , CPoint &cp )


{
double t = dot ( p1 , p2 , p0 ) / dot ( p1 , p2 , p2 ) ;
cp . x = p1 . x + t ∗ ( p2 . x−p1 . x ) ;
cp . y = p1 . y + t ∗ ( p2 . y−p1 . y ) ;
}

40
5.3 Convex Hull
Graham Scan, O(N log N )

CPoint bp ; // f o r p o l a r s o r t i n g

int PolarCmp ( const CPoint &p1 , const CPoint &p2 )


{
int u=dcmp ( c r o s s ( bp , p1 , p2 ) ) ;
return u > 0 | | ( u==0 && dcmp ( d i s s q r ( bp , p1)− d i s s q r ( bp , p2 ) ) < 0 ) ;
}

void GrahamScan ( CPoint p i n [ ] , int n , CPoint ch [ ] , int &m)


{
int i , j , k , u , v ;
memcpy ( ch , pin , n∗ s i z e o f ( CPoint ) ) ;
fo r ( i=k = 0 ; i <n ; i ++)
{
u = dcmp ( ch [ i ] . x − ch [ k ] . x ) ;
v = dcmp ( ch [ i ] . y − ch [ k ] . y ) ;
i f ( v < 0 | | ( v==0 && u < 0 ) ) k=i ;
}
bp = ch [ k ] ;
s t d : : s o r t ( ch , ch+n , PolarCmp ) ;
n = s t d : : unique ( ch , ch+n , PointEqual )−ch ;
i f ( n <=1 ) { m = n ; return ; }
i f ( dcmp ( c r o s s ( ch [ 0 ] , ch [ 1 ] , ch [ n −1]))==0 )
{ m= 2 ; ch [ 1 ] = ch [ n − 1 ] ; return ; }
ch [ n++]=ch [ 0 ] ;
fo r ( i =1, j = 2 ; j <n ; j ++)
{
while ( i >0 && dcmp ( c r o s s ( ch [ i −1] , ch [ i ] , ch [ j ] ) ) < = 0 ) i −−;
ch[++ i ] = ch [ j ] ;
}
m=i ;
}

void GrahamScanReserved ( CPoint p i n [ ] , int n , CPoint ch [ ] , int &m)


{
int i , j , k , u , v ;
memcpy ( ch , pin , n∗ s i z e o f ( CPoint ) ) ;
fo r ( i=k = 0 ; i <n ; i ++)
{
u = dcmp ( ch [ i ] . x − ch [ k ] . x ) ;
v = dcmp ( ch [ i ] . y − ch [ k ] . y ) ;
i f ( v < 0 | | ( v==0 && u < 0 ) ) k=i ;
}
bp = ch [ k ] ;
s t d : : s o r t ( ch , ch+n , PolarCmp ) ;
n = s t d : : unique ( ch , ch+n , PointEqual )−ch ;
i f ( n>0 && dcmp ( c r o s s ( ch [ 0 ] , ch [ 1 ] , ch [ n − 1 ] ) ) )
{
f o r ( i=n − 1 ; dcmp ( c r o s s ( ch [ 0 ] , ch [ n −1] , ch [ i ] ) ) = = 0 ; i −−);
s t d : : r e v e r s e ( ch+i +1, ch+n ) ;
}
fo r (m=0, i = 0 ; i <n ; i ++)
{
while ( m>=2 && dcmp ( c r o s s ( ch [m−2] , ch [m−1] , ch [ i ] ) ) < 0 ) m−−;
ch [m++] = ch [ i ] ;
}
}

41
Montone Chain, O(N log N )

int VerticalCmp ( const CPoint &p1 , const CPoint &p2 )


{
return p1 . y+eps<p2 . y | | ( p1 . y<p2 . y+e p s && p1 . x+eps<p2 . x ) ;
}

void MontoneChain ( CPoint p i n [ ] , int n , CPoint ch [ ] , int &m)


{
int i , k ; CPoint ∗ p = new CPoint [ n ] ;
memcpy ( p , pin , n∗ s i z e o f ( CPoint ) ) ;
s t d : : s o r t ( p , p+n , VerticalCmp ) ;
n = s t d : : unique ( p , p+n , PointEqual )−p ;
fo r ( m=i = 0 ; i <n ; i ++ )
{
while ( m>1 && dcmp ( c r o s s ( ch [m−2] , ch [m−1] , p [ i ] ) ) < = 0 ) m−−;
ch [m++]=p [ i ] ;
}
k=m;
fo r ( i=n − 2 ; i >=0; i −− )
{
while ( m>k && dcmp ( c r o s s ( ch [m−2] , ch [m−1] , p [ i ] ) ) < = 0 ) m−−;
ch [m++]=p [ i ] ;
}
i f ( n >1) m−−;
delete p ;
}

void MontoneChainReserved ( CPoint p i n [ ] , int n , CPoint ch [ ] , int &m)


{
int i , k ;
CPoint ∗ p = new CPoint [ n ] ; memcpy( p , pin , n∗ s i z e o f ( CPoint ) ) ;
s t d : : s o r t ( p , p+n , VerticalCmp ) ;
n = s t d : : unique ( p , p+n , PointEqual )−p ;
fo r ( m=i = 0 ; i <n ; i ++ )
{
while ( m>1 && dcmp ( c r o s s ( ch [m−2] , ch [m−1] , p [ i ] ) ) < 0 ) m−−;
ch [m++]=p [ i ] ;
}
i f ( n==m ) return ;
k=m;
fo r ( i=n − 2 ; i >=0; i −− )
{
while ( m>k && dcmp ( c r o s s ( ch [m−2] , ch [m−1] , p [ i ] ) ) < 0 ) m−−;
ch [m++]=p [ i ] ;
}
i f ( n >1) m−−;
delete p ;
}

42
Javis March, O(N H)

int ConvexJavisMarchCmp ( CPoint p0 , CPoint p1 , CPoint pnew )


{
int u=dcmp ( c r o s s ( p0 , p1 , pnew ) ) ;
return ( u < 0 | | ( u==0 && dcmp ( d i s s q r ( pnew , p0)− d i s s q r ( p1 , p0 ) ) > 0 ) ) ;
}

void ConvexJavisMarch ( CPoint p i n [ ] , int n , CPoint ch [ ] , int &m)


{
int i , j , k , u , v ;
char ∗mk = new char [ n ] ;
CPoint ∗ p = new CPoint [ n ] ;
memcpy ( p , pin , n∗ s i z e o f ( CPoint ) ) ;
memset (mk, 0 , n ) ;
fo r ( i=k=0; i <n ; i ++)
{
u=dcmp ( p [ i ] . x−p [ k ] . x ) ;
v=dcmp ( p [ i ] . y−p [ k ] . y ) ;
i f ( v < 0 | | ( v==0 && u < 0 ) ) k=i ;
}
fo r (m= 0 ; !mk [ k ] ; m++)
{
mk [ k ] = 1 ; ch [m]=p [ k ] ;
f o r ( j=k=0; j <n ; j ++) i f ( ConvexJavisMarchCmp ( ch [m] , p [ k ] , p [ j ] ) ) k=j ;
}
delete p ;
delete mk ;
}

5.4 Point Set Diameter


P must be convex in ccw order and no trhee points on an edge and will be changed after computing it’s convex hull
double Diameter ( CPoint ∗ p , int n )
{
Convex ( p , n , p , n ) ;
i f ( n==1 ) return 0 ;
i f ( n==2 ) return d i s ( p [ 0 ] , p [ 1 ] ) ;
int u , nu , v , nv , k ; double r e t = 0 ;
p[n] = p [ 0 ] ;
fo r ( u=0,v = 1 ; u<n ; u=nu )
{
nu = u+1;
while ( 1 ) {
nv = ( v+1)%n ;
k = dcmp ( ( p [ nu ] . x−p [ u ] . x ) ∗ ( p [ nv ] . y−p [ v ] . y )
− (p [ nv ] . x−p [ v ] . x ) ∗ ( p [ nu ] . y−p [ u ] . y ) ) ;
i f ( k <=0 ) break ;
v=nv ;
}
r e t = max ( r e t , d i s ( p [ u ] , p [ v ] ) ) ;
i f ( k ==0 ) r e t = max ( r e t , d i s ( p [ u ] , p [ nv ] ) ) ;
}
return r e t ;
}

43
5.5 Closest Pair
#define s q r ( z ) ( ( z ) ∗ ( z ) )
struct p o i n t { double x , y ; } pt [ maxn ] ; // [ 1 . . n ]
int n , o [ maxn ] , on ;

int dcmp ( double a , double b ) {


i f ( a − b < 1 e −10 && b − a < 1 e −10) return 0 ;
i f ( a > b ) return 1 ; return −1;
}

bool cmp( const p o i n t & a , const p o i n t & b )


{ return dcmp ( a . x , b . x ) < 0 ; }

bool cmp2 ( const int & a , const int & b )


{ return dcmp ( pt [ a ] . y , pt [ b ] . y ) < 0 ; }

double d i s ( p o i n t a , p o i n t b )
{ return s q r t ( s q r ( a . x − b . x ) + s q r ( a . y − b . y ) ) ; }

double min ( double a , double b ) { return a < b ? a : b ; }

double s e a r c h ( int s , int t ) {


int mid = ( s + t ) / 2 , i , j ; double r e t ( 1 e300 ) ;
i f ( s >= t ) return r e t ;
fo r ( i=mid ; i>=s && !dcmp ( pt [ i ] . x , pt [ mid ] . x ) ; i − −); r e t=s e a r c h ( s , i ) ;
fo r ( i=mid ; i<=t && !dcmp ( pt [ i ] . x , pt [ mid ] . x ) ; i ++);
r e t=min ( r e t , s e a r c h ( i , t ) ) ; on =0;
fo r ( i=mid ; i>=s && dcmp ( pt [ mid ] . x−pt [ i ] . x , r e t ) <=0; i −−) o[++on]= i ;
fo r ( i=mid + 1 ; i<=t && dcmp ( pt [ i ] . x−pt [ mid ] . x , r e t ) <= 0; i ++) o[++on]= i ;
s t d : : s o r t ( o+1,o+on+1,cmp2 ) ;
fo r ( i = 1 ; i<=on ; i ++) for ( j = 1 ; j <=10; j ++) i f ( i+j<=on )
r e t = min ( r e t , d i s ( pt [ o [ i ] ] , pt [ o [ i+j ] ] ) ) ;
return r e t ;
}

double s o l v e ( ) { s t d : : s o r t ( pt +1, pt+1+n , cmp ) ; return s e a r c h ( 1 , n ) ; }

5.6 Circles
Crossing of |P − P0 | = r and ax + by + c = 0

int C i r c l e C r o s s L i n e 1 ( CPoint p0 , double r ,


double a , double b , double c , CPoint &cp1 , CPoint & cp2 )
{
double aa = a ∗ a , bb = b ∗ b , s = aa + bb ;
double d = r ∗ r ∗ s − s q r ( a ∗p0 . x+b∗p0 . y+c ) ;
i f ( d+eps < 0 ) return 0 ;
i f ( d<e p s ) d = 0 ; e l s e d = s q r t ( d ) ;
double ab = a ∗ b , bd = b ∗ d , ad = a ∗ d ;
double xx = bb ∗ p0 . x − ab ∗ p0 . y − a ∗ c ;
double yy = aa ∗ p0 . y − ab ∗ p0 . x − b ∗ c ;
cp2 . x = ( xx + bd ) / s ; cp2 . y = ( yy − ad ) / s ;
cp1 . x = ( xx − bd ) / s ; cp1 . y = ( yy + ad ) / s ;
i f ( d>e p s ) return 2 ; e l s e return 1 ;
}

44
−−→
Crossing of |P − P0 | = r and P1 P2

int C i r c l e C r o s s L i n e 2 ( CPoint p0 , double r ,


CPoint p1 , CPoint p2 , CPoint &cp1 , CPoint & cp2 )
{
double d , d12 , dx , dy ;
d = f a b s ( PointToLine ( p0 , p1 , p2 , cp1 ) ) ;
i f ( dcmp ( d−r ) > 0 ) return 0 ;
i f ( dcmp ( d−r ) = = 0 ) { cp2 = cp1 ; return 1 ; }
d = s q r t ( r ∗ r − d∗d ) / d i s ( p1 , p2 ) ;
dx = ( p2 . x − p1 . x ) ∗ d ;
dy = ( p2 . y − p1 . y ) ∗ d ;
cp2 . x = cp1 . x + dx ; cp2 . y = cp1 . y + dy ;
cp1 . x = cp1 . x − dx ; cp1 . y = cp1 . y − dy ;
return 2 ;
}
Crossing of |P − P1 | = r1 and |P − P2 | = r2

int C i r c l e C r o s s C i r c l e 1 ( CPoint p1 , double r1 , CPoint p2 , double r2 ,


CPoint &cp1 , CPoint & cp2 )
{
double mx = p2 . x−p1 . x , sx = p2 . x+p1 . x , mx2 = mx∗mx ;
double my = p2 . y−p1 . y , sy = p2 . y+p1 . y , my2 = my∗my ;
double sq = mx2 + my2 , d = −( sq−s q r ( r1−r 2 ) ) ∗ ( sq−s q r ( r 1+r 2 ) ) ;
i f ( d+eps < 0 ) return 0 ; i f ( d<e p s ) d = 0 ; e l s e d = s q r t ( d ) ;
double x = mx ∗ ( ( r 1+r 2 ) ∗ ( r1−r 2 ) + mx∗ sx ) + sx ∗my2 ;
double y = my ∗ ( ( r 1+r 2 ) ∗ ( r1−r 2 ) + my∗ sy ) + sy ∗mx2 ;
double dx = mx∗d , dy = my∗d ; sq ∗ = 2 ;
cp1 . x = ( x − dy ) / sq ; cp1 . y = ( y + dx ) / sq ;
cp2 . x = ( x + dy ) / sq ; cp2 . y = ( y − dx ) / sq ;
i f ( d>e p s ) return 2 ; e l s e return 1 ;
}
Crossing of |P − P1 | = r1 and |P − P2 | = r2

int C i r c l e C r o s s C i r c l e 2 ( CPoint p1 , double r1 , CPoint p2 , double r2 ,


CPoint &cp1 , CPoint & cp2 )
{
double a , b , c ; CommonAxis ( p1 , r1 , p2 , r2 , a , b , c ) ;
return C i r c l e C r o s s L i n e 1 ( p1 , r1 , a , b , c , cp1 , cp2 ) ;
}
Common Axis of |P − P1 | = r1 and |P − P2 | = r2 of the ax + by + c = 0 form

void CommonAxis ( CPoint p1 , double r1 , CPoint p2 , double r2 ,


double &a , double &b , double & c )
{
double sx = p2 . x + p1 . x , mx = p2 . x − p1 . x ;
double sy = p2 . y + p1 . y , my = p2 . y − p1 . y ;
a = 2∗mx ; b = 2∗my ; c = − sx ∗mx − sy ∗my − ( r 1+r 2 ) ∗ ( r1−r 2 ) ;
}

45
5.7 Largest Empty Convex Polygon
#define ABS( x ) ( ( x ) >=0 ? ( x ) : − ( x ) )
#define CROSS( x1 , y1 , x2 , y2 ) ( ( x1 ) ∗ ( y2 )−( x2 ) ∗ ( y1 ) )

const double e p s = 1 e −8;

struct CPoint { int x , y ; } ;

int n ; CPoint p [ maxn ] ; double ans ;

bool cmp( const CPoint &a , const CPoint &b ) {


int v = CROSS ( a . x , a . y , b . x , b . y ) ;
i f ( v > 0 ) return true ; i f ( v < 0 ) return f a l s e ;
return ( a . x∗ a . x + a . y∗a . y < b . x∗b . x + b . y∗b . y ) ;
}

CPoint c [ maxn ] ; int nc ; double fm [ maxn ] [ maxn ] ;

void sweep ( int x , int y ) {


int i , j , k , m; double v , b e s t = 0 ;
fo r ( nc=i = 0 ; i <n; ++ i ) i f ( p [ i ] . y<y | | p [ i ] . y==y && p [ i ] . x<x )
{ c [ nc ] . x=p [ i ] . x−x ; c [ nc ++].y=p [ i ] . y−y ; }
i f ( nc < 2 ) return ;
s t d : : s o r t ( c , c + nc , cmp ) ;
memset ( fm , 0 , s i z e o f ( fm ) ) ;
fo r ( i = 1 ; i <nc ; ++ i ) {
j=i − 1 ; while ( j >=0 && CROSS( c [ i ] . x , c [ i ] . y , c [ j ] . x , c [ j ] . y)==0) −− j ;
int nev = 0 , ev [ maxn ] ;
while ( j >=0 ) {
v = CROSS( c [ j ] . x , c [ j ] . y , c [ i ] . x , c [ i ] . y ) / 2 . 0 ; k=j −1;
while ( k>=0 && CROSS ( c [ j ] . x−c [ i ] . x , c [ j ] . y−c [ i ] . y ,
c [ k ] . x−c [ i ] . x , c [ k ] . y−c [ i ] . y ) >0 ) − − k ;
i f ( k >=0 ) v += fm [ j ] [ k ] ;
i f ( v−b e s t >e p s ) b e s t = v ;
i f ( CROSS( c [ i ] . x , c [ i ] . y , c [ i − 1 ] . x , c [ i − 1 ] . y ) )
i f ( v−fm [ i ] [ j ]> e p s ) fm [ i ] [ j ]=v ;
ev [ nev++ ]= j ; j=k ;
}
i f ( CROSS( c [ i ] . x , c [ i ] . y , c [ i − 1 ] . x , c [ i − 1 ] . y ) )
f o r ( j=nev − 2 ; j >=0; −− j ) i f ( fm [ i ] [ ev [ j +1]] −fm [ i ] [ ev [ j ]] > e p s )
fm [ i ] [ ev [ j ] ] = fm [ i ] [ ev [ j + 1 ] ] ;
}
i f ( b e s t −ans>e p s ) ans = b e s t ;
}

void main ( ) {
int t , i ; f or ( s c a n f ( ”%d” , & t ) ; t ; −− t ) { s c a n f ( ”%d” , & n ) ;
f o r ( i = 0 ; i <n; ++ i ) s c a n f ( ”%d %d” , & p [ i ] . x , & p [ i ] . y ) ;
f o r ( ans=i = 0 ; i <n; ++ i ) sweep ( p [ i ] . x , p [ i ] . y ) ; // main p r o c e d u r e
p r i n t f ( ”%.1 l f \n” , ans ) ;
}
}

46
5.8 Triangle Centers
// INPUT : ( 2 4 2 , 8 9 ) , ( 2 1 2 , 1 8 5 ) , ( 7 1 , 1 2 8 ) , OUTPUT: ( 1 5 8 . 0 8 8 5 , 1 1 5 . 4 6 5 2 )
void C i r c u m c e n t e r ( CPoint p0 , CPoint p1 , CPoint p2 , CPoint &cp )
{
double a1=p1 . x−p0 . x , b1=p1 . y−p0 . y , c1=( s q r ( a1)+ s q r ( b1 ) ) / 2 ;
double a2=p2 . x−p0 . x , b2=p2 . y−p0 . y , c2=( s q r ( a2)+ s q r ( b2 ) ) / 2 ;
double d = a1 ∗ b2 − a2 ∗ b1 ;
cp . x = p0 . x + ( c1 ∗b2 − c2 ∗b1 ) / d ;
cp . y = p0 . y + ( a1 ∗ c2 − a2 ∗ c1 ) / d ;
}

// INPUT : ( 2 4 2 , 8 9 ) , ( 2 1 2 , 1 8 5 ) , ( 7 1 , 1 2 8 ) , OUTPUT: ( 1 8 9 . 5 2 8 6 , 1 3 7 . 4 9 8 7 )
double I n c e n t e r ( CPoint A, CPoint B , CPoint C , CPoint &cp )
{
double s , p , r , a , b , c ;
a = d i s (B , C) , b = d i s (C , A) , c = d i s (A, B ) ; p = ( a + b + c ) / 2 ;
s = s q r t ( p ∗ ( p−a ) ∗ ( p−b ) ∗ ( p−c ) ) ; r = s / p;
cp . x = ( a ∗A. x + b∗B . x + c ∗C. x ) / ( a + b + c ) ;
cp . y = ( a ∗A. y + b∗B . y + c ∗C. y ) / ( a + b + c ) ;
return r ;
}

// INPUT : ( 2 4 2 , 8 9 ) , ( 2 1 2 , 1 8 5 ) , ( 7 1 , 1 2 8 ) , OUTPUT: ( 2 0 8 . 8 2 2 9 , 1 7 1 . 0 6 9 7 )
void O r t h o c e n t e r ( CPoint A, CPoint B , CPoint C , CPoint &cp )
{
C i r c u m c e n t e r (A, B , C , cp ) ;
cp . x = A. x + B . x + C. x − 2 ∗ cp . x ;
cp . y = A. y + B . y + C. y − 2 ∗ cp . y ;
}
Find three numbers r, s, t which make P = rA + sB + tC and r + s + t = 1

void P a r a m e t r i c ( CPoint P , CPoint A , CPoint B , CPoint C ,


double &r , double &s , double & t )
{
double d ;
d = c r o s s ( A, B , C ) ;
r = c r o s s ( P , B, C) / d ;
s = c r o s s ( A, P , C ) / d ;
t = c r o s s ( A, B , P ) / d ;
}

void P o l y g o n C e n t r o i d s ( CPoint p [ ] , int n , CPoint &cp )


{
double sum=0 , s = 0 ; cp . x = 0 ; cp . y=0;
fo r ( int i = 1 ; i <n − 1 ; i ++,sum+=s )
{
s= cross ( p [ 0 ] , p [ i ] , p [ i +1] );
cp . x += s ∗ ( p [ 0 ] . x + p [ i ] . x + p [ i + 1 ] . x ) ;
cp . y += s ∗ ( p [ 0 ] . y + p [ i ] . y + p [ i + 1 ] . y ) ;
}
cp . x/=sum ∗ 3 ; cp . y/=sum ∗ 3 ;
}

47
5.9 Polyhedron Volume
Remark : All faces are assumed oriented counterclockwise from the outside;
Volume6 returns six times the volume of the tetrahedron determined by abc
and the origin d. Volume6 is positive iff d is on the negative side of abc,
where the positive side is determined by the rh-rule. So the volume is positive
if the ccw normal to abc points outside the tetrahedron.
struct TPoint { double x , y , z ; } ;
typedef int TFace [ 3 ] ;

double Volume6 ( TPoint a , TPoint b , TPoint c , TPoint d ) // d = o r i g i n


{
double vol , bdx , bdy , bdz , cdx , cdy , cdz ;
bdx = b . x−d . x ; bdy = b . y−d . y ; bdz = b . z−d . z ;
cdx = c . x−d . x ; cdy = c . y−d . y ; cdz = c . z−d . z ;
v o l = ( a . z − d . z ) ∗ ( bdx ∗ cdy − bdy ∗ cdx )
+ ( a . y − d . y ) ∗ ( bdz ∗ cdx − bdx ∗ cdz )
+ ( a . x − d . x ) ∗ ( bdy ∗ cdz − bdz ∗ cdy ) ;
return v o l ;
}

void main ( )
{
int n , F , i , j ; double v o l ;
TPoint p [ maxn ] ; TFace f a c e [ maxn∗2 −4];
c i n >>n ; f o r ( i = 0 ; i <n ; i ++) c i n >> p [ i ] . x >> p [ i ] . y >> p [ i ] . z ;
c i n >>F ; f o r ( i = 0 ; i <F ; i ++) for ( j =0; j <3; j ++) c i n >> f a c e [ i ] [ j ] ;
i f ( F ! = 2 ∗ n − 4 ) { p r i n t f ( ”Not a s i m p l e p o l y h e d r o n ! \ n” ) ; return ; }
for ( v o l = i = 0 ; i < F ; i ++ )
v o l += Volume6 ( p [ f a c e [ i ] [ 0 ] ] , p [ f a c e [ i ] [ 1 ] ] , p [ f a c e [ i ] [ 2 ] ] , p [ 0 ] ) ;
v o l / = 6 . 0 ; c o u t << v o l <<e n d l ;
}

48
5.10 Planar Graph Contour
int x [ maxn ] , y [ maxn ] , g [ maxn ] [ maxn ] , num [ maxn ] , base , n , s i z e , mk [ maxn ] [ maxn ] ;
int s [ maxn ] , used [ maxn ] , ans ; double a n g l e [ maxn ] ;

bool cmp( const int & i , const int&j ) { return a n g l e [ i ] < a n g l e [ j ] ; }

void d f s ( int d , int u , int v )


{
int i , j ,w ; s [ d ] = u ; used [ u]++;
i f ( mk [ u ] [ v ] ) {
i f ( d==s i z e ) {
used [ u]−−;
f o r ( j =1; j<=n ; j ++) i f ( used [ j ] > 1 ) break ; i f ( j<=n ) return ;
i f ( j >n) ++ ans ;
}
return ;
}
mk [ u ] [ v ] = 1 ;
fo r ( j = 0 ; j <num [ v ] ; j ++) i f ( g [ v ] [ j ]==u ) break ;
j = ( j +1)%num [ v ] ; w = g [ v ] [ j ] ; d f s ( d +1 , v , w ) ;
}

void s o l v e ( )
{
int i , j , k , l , u , v ;
fo r ( i = 1 ; i<=n ; i ++){
b a s e=i ;
f o r ( j = 1 ; j<=n ; j ++) a n g l e [ j ] = atan2 ( y [ j ]−y [ i ] , x [ j ]−x [ i ] ) ;
s t d : : s o r t ( g [ i ] , g [ i ]+num [ i ] , cmp ) ;
}
u = 1 ; memset (mk , 0 , s i z e o f (mk ) ) ;
fo r ( i = 2 ; i<=n ; i ++) i f ( y [ i ]<y [ u ] | | ( y [ i ]==y [ u ] && x [ i ]<x [ u ] ) ) u=i ;
fo r ( v=−1, i = 0 ; i <num [ u ] ; i ++) {
j = g [ u ] [ i ] ; i f ( j==u | | j==v ) continue ;
i f ( v < 0 ) { v=j ; continue ; }
k = ( x [ j ]−x [ u ] ) ∗ ( y [ v]−y [ u ]) −( y [ j ]−y [ u ] ) ∗ ( x [ v]−x [ u ] ) ;
i f ( k < 0 ) v=j ; e l s e
i f ( k ==0 ) i f ( y [ j ]<y [ v ] | | ( y [ j ]==y [ v ] && x [ j ]<x [ v ] ) ) v=j ;
}
d f s ( 0 , v , u ) ; ans = 0 ; // o u t e r c o n t o u r
fo r ( i = 1 ; i<=n ; i ++) for ( j = 0 ; j <num [ i ] ; j ++)
i f ( ! mk [ i ] [ g [ i ] [ j ] ] )
{
memset ( used , 0 , s i z e o f ( used ) ) ;
dfs (0 , i , g [ i ] [ j ] ) ;
}
}

int main ( )
{
int t , i , j , k , l ;
c i n >>t ; while ( t −−>0) {
c i n >>n ;
f o r ( k = 0 ; k<n ; k++) {
c i n >>i ; c i n >>x [ i ]>>y [ i ] ; c i n >>num [ i ] ;
f o r ( j =0; j <num [ i ] ; j ++) c i n >>g [ i ] [ j ] ;
}
c i n >>s i z e ; ans = 0 ; i f ( s i z e <3) s i z e =3;
s o l v e ( ) ; cout<<ans<<e n d l ;
} return 0 ;
}

49
5.11 Rectangles Area
struct TSegNode {
TSegNode ( int x , int y ) : L( x ) ,R( y ) , Lch ( −1) ,Rch( −1) , count ( 0 ) , l e n ( 0 ) { }
TSegNode ( ) { TSegNode ( −1 , −1);}
int L , R , Lch , Rch , count , l e n ;
};

struct Tevent {
int L , R , x ;
bool s t y l e ;
friend const bool operator < ( Tevent a , Tevent b ) { return a . x<b . x ; }
};

int n l i s t , l i s t [MAXN∗ 4 ] , t o t a l , n , nevent ;


TSegNode node [MAXN∗ 4 ] ; Tevent e v e n t [MAXN∗ 4 ] ;

void C r e a t e T r e e ( int r ) {
i f ( node [ r ] . R−node [ r ] . L> 1 ) {
int mid = ( node [ r ] . L+node [ r ] . R)>>1;
node [ t o t a l ] = TSegNode ( node [ r ] . L , mid ) ;
node [ r ] . Lch = t o t a l ; C re a te T r e e ( t o t a l ++);
node [ t o t a l ] = TSegNode ( mid , node [ r ] . R ) ;
node [ r ] . Rch = t o t a l ; C re a te T r e e ( t o t a l ++);
}
}

void Update ( int r , int L , int R , int v ) {


i f ( L>=node [ r ] . R | | R<=node [ r ] . L ) return ;
i f ( L<=node [ r ] . L && R>=node [ r ] . R ) {
node [ r ] . count+=v ;
i f ( v>0 && v==node [ r ] . count ) node [ r ] . l e n = node [ r ] . R−node [ r ] . L ;
i f ( v<0 && node [ r ] . count ==0 ) i f ( node [ r ] . Lch < 0 ) node [ r ] . l e n = 0 ;
e l s e node [ r ] . l e n = node [ node [ r ] . Lch ] . l e n + node [ node [ r ] . Rch ] . l e n ;
} else {
Update ( node [ r ] . Lch , L , R , v ) ; Update ( node [ r ] . Rch , L , R , v ) ;
i f ( node [ r ] . count ==0 ) node [ r ] . l e n =
node [ node [ r ] . Lch ] . l e n + node [ node [ r ] . Rch ] . l e n ;
}
}

50
int main ( ) {
int i , j , r e s , l a s t ;
s c a n f ( ”%d” , & n ) ;
nevent = 0 ; n l i s t =0;
fo r ( i = 0 ; i <n; ++ i ) {
int lx , ly , ux , uy ;
s c a n f ( ”%d %d %d %d” , & lx , & ly , & ux , & uy ) ;
i f ( lx <ux && ly <uy ) {
e v e n t [ nevent ] . x = l x ; e v e n t [ nevent ] . L = l y ;
e v e n t [ nevent ] . R = uy ; e v e n t [ nevent ++]. s t y l e = true ;
e v e n t [ nevent ] . x = ux ; e v e n t [ nevent ] . L = l y ;
e v e n t [ nevent ] . R = uy ; e v e n t [ nevent ++]. s t y l e = f a l s e ;
}
l i s t [ n l i s t ++] = l y ; l i s t [ n l i s t ++] = uy ;
}
s t d : : s o r t ( event , e v e n t+nevent ) ;
s t d : : s o r t ( l i s t , l i s t +n l i s t ) ;
n l i s t = s t d : : unique ( l i s t , l i s t +n l i s t )− l i s t ;
node [ t o t a l =0 , t o t a l ++] = TSegNode ( 0 , n l i s t −1);
CreateTree ( 0 ) ;
fo r ( i = 0 ; i <t o t a l ; ++ i )
{ node [ i ] . L = l i s t [ node [ i ] . L ] ; node [ i ] . R = l i s t [ node [ i ] . R ] ; }
res = i = 0;
while ( i <nevent ) {
f o r ( l a s t=e v e n t [ i ] . x ; e v e n t [ i ] . x==l a s t ; ++ i )
Update ( 0 , e v e n t [ i ] . L , e v e n t [ i ] . R , e v e n t [ i ] . s t y l e ? 1 : − 1 ) ;
i f ( i < nevent ) r e s += ( e v e n t [ i ] . x − l a s t ) ∗ node [ 0 ] . l e n ;
}
p r i n t f ( ”%d\n” , r e s ) ;
return 0 ;
}

51
5.12 Rectangles Perimeter
#define ABS( x ) ( ( x ) >=0 ? ( x ) : − ( x ) )

struct TSegNode {
TSegNode ( int x , int y ) : L( x ) ,R( y ) , Lch ( −1) ,Rch( −1) , count ( 0 ) , l e n ( 0 ) { }
TSegNode ( ) { TSegNode ( −1 , −1);}
int L , R , Lch , Rch , count , l e n ;
};

struct Tevent {
int L , R , x ; bool s t y l e ;
friend const bool operator < ( Tevent a , Tevent b )
{ i f ( a . x!=b . x ) return a . x<b . x ; return ( a . s t y l e && ! b . s t y l e ) ; }
};

int n , l x [MAXN] , l y [MAXN] , ux [MAXN] , uy [MAXN] , t o t a l , nevent , r e s ;


TSegNode node [MAXN∗ 4 ] ; Tevent e v e n t [MAXN∗ 4 ] ;

void C r e a t e T r e e ( int r ) {
i f ( node [ r ] . R−node [ r ] . L> 1 ) {
int mid = ( node [ r ] . L+node [ r ] . R)>>1;
node [ t o t a l ] = TSegNode ( node [ r ] . L , mid ) ;
node [ r ] . Lch = t o t a l ; C re a te T r e e ( t o t a l ++);
node [ t o t a l ] = TSegNode ( mid , node [ r ] . R ) ;
node [ r ] . Rch = t o t a l ; C re a te T r e e ( t o t a l ++);
}
}

void Update ( int r , int L , int R , int v ) {


i f ( L>=node [ r ] . R | | R<=node [ r ] . L ) return ;
i f ( L<=node [ r ] . L && R>=node [ r ] . R ) {
node [ r ] . count+=v ;
i f ( v>0 && v==node [ r ] . count ) node [ r ] . l e n = node [ r ] . R−node [ r ] . L ;
i f ( v<0 && node [ r ] . count ==0 ) i f ( node [ r ] . Lch < 0 ) node [ r ] . l e n = 0 ;
e l s e node [ r ] . l e n = node [ node [ r ] . Lch ] . l e n + node [ node [ r ] . Rch ] . l e n ;
} else {
Update ( node [ r ] . Lch , L , R , v ) ; Update ( node [ r ] . Rch , L , R , v ) ;
i f ( node [ r ] . count ==0 ) node [ r ] . l e n =
node [ node [ r ] . Lch ] . l e n + node [ node [ r ] . Rch ] . l e n ;
}
}

52
void p r o c e s s ( ) {
int n l i s t , l i s t [MAXN∗ 2 ] , l a s t , i , now ;
nevent = 0 ; n l i s t = 0 ;
fo r ( i = 0 ; i <n; ++ i ) {
e v e n t [ nevent ] . x = l x [ i ] ; e v e n t [ nevent ] . L = ly [ i ] ;
e v e n t [ nevent ] . R = uy [ i ] ; e v e n t [ nevent ++]. s t y l e = true ;
e v e n t [ nevent ] . x = ux [ i ] ; e v e n t [ nevent ] . L = ly [ i ] ;
e v e n t [ nevent ] . R = uy [ i ] ; e v e n t [ nevent ++]. s t y l e = f a l s e ;
l i s t [ n l i s t ++] = ly [ i ] ; l i s t [ n l i s t ++] = uy [ i ] ;
}
s t d : : s o r t ( event , e v e n t+nevent ) ;
s t d : : s o r t ( l i s t , l i s t +n l i s t ) ;
n l i s t = int ( s t d : : unique ( l i s t , l i s t +n l i s t )− l i s t ) ;
node [ t o t a l =0 , t o t a l ++] = TSegNode ( 0 , n l i s t −1);
CreateTree ( 0 ) ;
fo r ( i = 0 ; i <t o t a l ; ++ i )
{ node [ i ] . L = l i s t [ node [ i ] . L ] ; node [ i ] . R = l i s t [ node [ i ] . R ] ; }
las t = i = 0;
while ( i <nevent ) {
now = e v e n t [ i ] . x ;
while ( i <nevent && e v e n t [ i ] . x==now && e v e n t [ i ] . s t y l e )
{ Update ( 0 , e v e n t [ i ] . L , e v e n t [ i ] . R, 1 ) ; + + i ; }
r e s += ABS( node [ 0 ] . l e n −l a s t ) ; l a s t = node [ 0 ] . l e n ;
while ( i <nevent && e v e n t [ i ] . x==now )
{ Update ( 0 , e v e n t [ i ] . L , e v e n t [ i ] . R, −1); ++ i ; }
r e s += ABS( node [ 0 ] . l e n −l a s t ) ; l a s t = node [ 0 ] . l e n ;
}
}

int main ( ) {
int i ;
s c a n f ( ”%d” , & n ) ;
fo r ( i = 0 ; i <n; ++ i ) s c a n f ( ”%d %d %d %d” ,& l x [ i ] ,& l y [ i ] ,& ux [ i ] ,& uy [ i ] ) ;
r e s =0; p r o c e s s ( ) ;
fo r ( i = 0 ; i <n; ++ i ) { s t d : : swap ( l x [ i ] , l y [ i ] ) ; s t d : : swap ( ux [ i ] , uy [ i ] ) ; }
p r o c e s s ( ) ; p r i n t f ( ”%d\n” , r e s ) ;
return 0 ;
}

53
5.13 Smallest Enclosing Circle
O(N 3 ), compute Convex Hull first! or it will be quite slow!
double GetCos ( CPoint p0 , CPoint p1 , CPoint p2 )
{ return dot ( p0 , p1 , p2 ) / d i s ( p0 , p1 ) / d i s ( p0 , p2 ) ; }

int a l l i n ( CPoint p [ ] , int n , int i , int j , int k )


{
fo r ( int l = 0 ; l <n ; l ++) i f ( l != i && l != j && l !=k ) {
i f ( ( c r o s s (p [ i ] , p [ j ] , p [ k ]) >0)ˆ( c r o s s (p [ i ] , p [ j ] , p [ l ]) >0) &&
dcmp ( GetCos ( p [ k ] , p [ i ] , p [ j ])+ GetCos ( p [ l ] , p [ i ] , p [ j ] ) ) > 0 ) return 0 ;
i f ( ( c r o s s (p [ j ] , p [ k ] , p [ i ]) >0)ˆ( c r o s s (p [ j ] , p [ k ] , p [ l ]) >0) &&
dcmp ( GetCos ( p [ i ] , p [ k ] , p [ j ])+ GetCos ( p [ l ] , p [ k ] , p [ j ] ) ) > 0 ) return 0 ;
i f ( ( c r o s s (p [ i ] , p [ j ] , p [ k ]) >0)ˆ( c r o s s (p [ i ] , p [ l ] , p [ k]) >0) &&
dcmp ( GetCos ( p [ j ] , p [ k ] , p [ i ])+ GetCos ( p [ l ] , p [ k ] , p [ i ] ) ) > 0 ) return 0 ;
}
return 1 ;
}

double S m a l l e s t E n c l o s i n g C i r c l e ( CPoint p [ ] , int n , CPoint &cp )


{
int i , j , k ; double di , cos1 , cos2 , co , s i , r =0;
i f ( n = = 1 ) { cp = p [ 0 ] ; return 0 ; }
i f ( n == 2 )
{
cp . x = ( p [ 0 ] . x + p [ 1 ] . x ) / 2 ;
cp . y = ( p [ 0 ] . y + p [ 1 ] . y ) / 2 ;
return d i s ( p [ 0 ] , p [ 1 ] ) / 2 ;
}
fo r ( i = 0 ; i <n ; i ++) for ( j=i + 1 ; j <n ; j ++)
{
d i = d i s ( p [ i ] , p [ j ] ) ; c o s 1 = c o s 2 = −2;
i f ( dcmp ( di−r ∗ 2 ) > 0 ) r = d i / 2 ;
f o r ( k = 0 ; k<n ; k++) i f ( k!= i && k!= j )
{
co = GetCos ( p [ k ] , p [ i ] , p [ j ] ) ;
i f ( dcmp ( c r o s s ( p [ i ] , p [ j ] , p [ k ] ) ) > 0 )
{ i f ( co>c o s 1 ) c o s 1=co ; }
e l s e i f ( co>c o s 2 ) c o s 2=co ;
}
i f ( dcmp ( c o s 1 )<=0 && dcmp ( c o s 2 ) <=0 )
{
cp . x = ( p [ i ] . x + p [ j ] . x ) / 2 ;
cp . y = ( p [ i ] . y + p [ j ] . y ) / 2 ;
return d i / 2 ;
}
}
r = 1 e30 ;
fo r ( i = 0 ; i <n ; i ++) for ( j=i + 1 ; j <n ; j ++) {
di = dis ( p [ i ] , p [ j ] ) ;
f o r ( k=j + 1 ; k<n ; k++) {
co = GetCos ( p [ k ] , p [ j ] , p [ i ] ) ;
s i = s q r t (1− s q r ( co ) ) ;
i f ( dcmp ( d i / s i /2− r )<0 && a l l i n ( p , n , i , j , k ) ) {
r=d i / s i / 2 ;
G e t C i r c l e C e n t e r ( p [ i ] , p [ j ] , p [ k ] , cp ) ;
}
}
}
return r ;
}

54
5.14 Smallest Enclosing Ball
const double e p s = 1 e −10;

struct p o i n t t y p e { double x , y , z ; } ;

int npoint , n o u t e r ;
point type point [ 1 0 0 0 0 ] , outer [ 4 ] , res ;
double r a d i u s , tmp ;

i n l i n e double d i s t ( p o i n t t y p e p1 , p o i n t t y p e p2 )
{
double dx=p1 . x−p2 . x , dy=p1 . y−p2 . y , dz=p1 . z−p2 . z ;
return ( dx∗dx + dy∗dy + dz ∗ dz ) ;
}

i n l i n e double dot ( p o i n t t y p e p1 , p o i n t t y p e p2 )
{
return p1 . x∗p2 . x + p1 . y∗p2 . y + p1 . z ∗p2 . z ;
}

void m i n b a l l ( int n )
{
ball ();
i f ( nouter <4 )
f o r ( int i = 0 ; i <n; ++ i )
i f ( d i s t ( r e s , p o i n t [ i ]) − r a d i u s >e p s )
{
o u t e r [ n o u t e r ]= p o i n t [ i ] ;
++n o u t e r ;
minball ( i ) ;
−−n o u t e r ;
i f ( i >0 )
{
p o i n t t y p e Tt = p o i n t [ i ] ;
memmove(& p o i n t [ 1 ] , & p o i n t [ 0 ] , s i z e o f ( p o i n t t y p e ) ∗ i ) ;
p o i n t [ 0 ] = Tt ;
}
}
}

55
void b a l l ( ) {
p o i n t t y p e q [ 3 ] ; double m[ 3 ] [ 3 ] , s o l [ 3 ] , L [ 3 ] , d e t ; int i , j ;
res . x = res . y = res . z = radius = 0;
switch ( n o u t e r ) {
case 1 : r e s=o u t e r [ 0 ] ; break ;
case 2 :
r e s . x=( o u t e r [ 0 ] . x+o u t e r [ 1 ] . x ) / 2 ;
r e s . y=( o u t e r [ 0 ] . y+o u t e r [ 1 ] . y ) / 2 ;
r e s . z=( o u t e r [ 0 ] . z+o u t e r [ 1 ] . z ) / 2 ;
r a d i u s=d i s t ( r e s , o u t e r [ 0 ] ) ;
break ;
case 3 :
f o r ( i = 0 ; i <2; ++ i ) {
q [ i ] . x=o u t e r [ i + 1 ] . x−o u t e r [ 0 ] . x ;
q [ i ] . y=o u t e r [ i + 1 ] . y−o u t e r [ 0 ] . y ;
q [ i ] . z=o u t e r [ i + 1 ] . z−o u t e r [ 0 ] . z ;
}
f o r ( i = 0 ; i <2; ++ i ) for ( j = 0 ; j <2; ++ j )
m[ i ] [ j ]= dot ( q [ i ] , q [ j ] ) ∗ 2 ;
f o r ( i = 0 ; i <2; ++ i ) s o l [ i ]= dot ( q [ i ] , q [ i ] ) ;
i f ( f a b s ( d e t=m[ 0 ] [ 0 ] ∗m[ 1 ] [ 1 ] −m[ 0 ] [ 1 ] ∗m[ 1 ] [ 0 ] ) < e p s ) return ;

L [ 0 ] = ( s o l [ 0 ] ∗m[ 1 ] [ 1 ] − s o l [ 1 ] ∗m[ 0 ] [ 1 ] ) / d e t ;
L [ 1 ] = ( s o l [ 1 ] ∗m[ 0 ] [ 0 ] − s o l [ 0 ] ∗m[ 1 ] [ 0 ] ) / d e t ;

r e s . x=o u t e r [ 0 ] . x+q [ 0 ] . x∗L [ 0 ] + q [ 1 ] . x∗L [ 1 ] ;


r e s . y=o u t e r [ 0 ] . y+q [ 0 ] . y∗L [ 0 ] + q [ 1 ] . y∗L [ 1 ] ;
r e s . z=o u t e r [ 0 ] . z+q [ 0 ] . z ∗L [ 0 ] + q [ 1 ] . z ∗L [ 1 ] ;
r a d i u s=d i s t ( r e s , o u t e r [ 0 ] ) ;
break ;
case 4 :
f o r ( i = 0 ; i <3; ++ i ) {
q [ i ] . x=o u t e r [ i + 1 ] . x−o u t e r [ 0 ] . x ;
q [ i ] . y=o u t e r [ i + 1 ] . y−o u t e r [ 0 ] . y ;
q [ i ] . z=o u t e r [ i + 1 ] . z−o u t e r [ 0 ] . z ;
s o l [ i ]= dot ( q [ i ] , q [ i ] ) ;
}
f o r ( i =0; i <3;++ i ) for ( j =0; j <3;++ j ) m[ i ] [ j ]= dot ( q [ i ] , q [ j ] ) ∗ 2 ;
d e t = m[ 0 ] [ 0 ] ∗m[ 1 ] [ 1 ] ∗m[ 2 ] [ 2 ] + m[ 0 ] [ 1 ] ∗m[ 1 ] [ 2 ] ∗m[ 2 ] [ 0 ]
+ m[ 0 ] [ 2 ] ∗m[ 2 ] [ 1 ] ∗m[ 1 ] [ 0 ] − m[ 0 ] [ 2 ] ∗m[ 1 ] [ 1 ] ∗m[ 2 ] [ 0 ]
− m[ 0 ] [ 1 ] ∗m[ 1 ] [ 0 ] ∗m[ 2 ] [ 2 ] − m[ 0 ] [ 0 ] ∗m[ 1 ] [ 2 ] ∗m [ 2 ] [ 1 ] ;

i f ( f a b s ( d e t )< e p s ) return ;

f o r ( j = 0 ; j <3; ++ j ) {
for ( i = 0 ; i <3; ++ i ) m[ i ] [ j ]= s o l [ i ] ;
L [ j ] = ( m[ 0 ] [ 0 ] ∗m[ 1 ] [ 1 ] ∗m[ 2 ] [ 2 ] + m[ 0 ] [ 1 ] ∗m[ 1 ] [ 2 ] ∗m[ 2 ] [ 0 ]
+ m[ 0 ] [ 2 ] ∗m[ 2 ] [ 1 ] ∗m[ 1 ] [ 0 ] − m[ 0 ] [ 2 ] ∗m[ 1 ] [ 1 ] ∗m[ 2 ] [ 0 ]
− m[ 0 ] [ 1 ] ∗m[ 1 ] [ 0 ] ∗m[ 2 ] [ 2 ] − m[ 0 ] [ 0 ] ∗m[ 1 ] [ 2 ] ∗m[ 2 ] [ 1 ]
) / det ;
for ( i = 0 ; i <3; ++ i ) m[ i ] [ j ]= dot ( q [ i ] , q [ j ] ) ∗ 2 ;
}
r e s=o u t e r [ 0 ] ;
f o r ( i = 0 ; i <3; ++ i ) {
r e s . x += q [ i ] . x ∗ L [ i ] ;
r e s . y += q [ i ] . y ∗ L [ i ] ;
r e s . z += q [ i ] . z ∗ L [ i ] ;
}
r a d i u s=d i s t ( r e s , o u t e r [ 0 ] ) ;
}
}

56
Chapter 6

Classic Problems

6.1 Bernoulli Number Generator


Note: fraction.h contains a Fraction Class (Section 1.4 on Page 8)
#include<f r a c t i o n . h>

Fraction a [ 2 2 ] ;
int c [ 2 2 ] [ 2 2 ] ;

int main ( )
{
int i , j , k ,m;
c [0][0] = 1;
fo r ( i =1; i <=21; i ++) {
c [ i ][0] = 1; c [ i ] [ i ] = 1;
f o r ( j =1; j <i ; j ++) c [ i ] [ j ] = c [ i − 1 ] [ j ] + c [ i − 1 ] [ j − 1 ] ;
}
a[0] = 0;
while ( c i n >>k ) {
a [ k +1] = F r a c t i o n ( 1 , k + 1 ) ; m = k+1;
f o r ( i=k ; i >=1; i −−) {
a [ i ] = 0;
f o r ( j=i +1; j<=k+1; j ++)
i f ( ( j −i +1)%2==0) a [ i ] = a [ i ]+a [ j ] ∗ c [ j ] [ j −i + 1 ] ;
e l s e a [ i ] = a [ i ]−a [ j ] ∗ c [ j ] [ j −i + 1 ] ;
a [ i ] = a [ i ] ∗ Fraction (1 , i ) ;
m = lcm (m, a [ i ] . g e t d e n o m i n a t o r ( ) ) ;
}
c o u t << m << ’ ’ ;
f o r ( i=k+1; i >0; i −−) c o u t << a [ i ] ∗ m<< ’ ’ ;
c o u t << 0 << e n d l ;
}
return 0 ;
}

57
6.2 Baltic OI’99 Expressions
f (n, d) is the number of trees whose depth is less or equal than d.
int f [ maxn ] [ maxd ] , h [ maxn ] [ maxn ] , n , d ;

int main ( )
{
ifstream cin ( ” input . txt ” ) ;
int i , j , k ;
fo r ( d = 1 ; d<maxd ; d++) {
memset ( h , 0 , s i z e o f ( h ) ) ;
f o r ( i = 0 ; i<=d ; i ++) h [ i ] [ 0 ] = 1 ;
f o r ( i = 1 ; i <maxn ; i ++) for ( j=i −d ; j<=i ; j ++)
i f ( j >=0) h [ i ] [ j ]=h [ i − 1 ] [ j ]+h [ i ] [ j − 1 ] ;
f o r ( i =1; i <maxn ; i ++) f [ i ] [ d]=h [ i ] [ i ] ;
}
while ( c i n >>n>>d && n ) cout << f [ n / 2 ] [ d ] − f [ n / 2 ] [ d−1]<<e n d l ;
return 0 ;
}

6.3 Bead Coloring — Pólya Theory


Use C colors to color L-bead necklace , the non-isomorphic number of the necklaces is :

If L is odd ,
L
1 L+1 X
f (C, L) = (LC 2 + C (K,L) )
2L
K=1

If L is even,
L
1 L L L
X
f (C, L) = ( (C 2 + C 2 +1 ) + C (K,L) )
2L 2
K=1

int ans , n ,m, mk [ maxn ] , i d [ maxn ] , num ;

int main ( )
{
int i , j , k , l , d , u , p [ maxn ] ;
while ( c i n >>n>>m && n && m) {
f o r ( p [ 0 ] = i = 1 ; i<=m; i ++) p [ i ]=p [ i −1]∗n ;
f o r ( ans=num=i =0; i <m; i ++) i d [ i ]= i ;
f o r ( l =0; l <2; l ++){
f o r ( i =0; i <m; i ++) {
memset (mk, 0 , s i z e o f (mk ) ) ;
for ( k=j =0; j <m; j ++) i f ( ! mk [ i d [ j ] ] )
for ( k++, u=i d [ j ] ; ! mk [ u ] ; u=i d [ ( u+i )%m] ) mk [ u ] = 1 ;
num++; ans+=p [ k ] ;
}
s t d : : r e v e r s e ( id , i d+m) ;
} cout<<ans /num<<e n d l ;
}
return 0 ;
}

58
6.4 Binary Stirling Number
Parity of the Stirling number of the second kind
#define int long long

int c a l c ( int n , int k )


{
i f ( k ==0 ) i f ( n==0 ) return 1 ; e l s e return 0 ;
e l s e i f ( k ==1 ) return 1 ; e l s e
{
int p = 0 , p2 = 1 ;
while ( k>p2 ∗ 2 | | n−k/2>p2 ) { p++; p2 <<=1; }
i f ( k>p2 ) return c a l c ( n−p2 , k−p2 ) ;
i f ( n−k>=p2 / 2 ) return c a l c ( n−p2 / 2 , k ) ;
return 0 ;
}
}

6.5 Box Surface Distance


int r , L , H,W, x1 , y1 , z1 , x2 , y2 , z2 ;

void t u r n ( int i , int j , int x , int y , int z , int x0 , int y0 , int L , int W, int H) {
i f ( z ==0){ int R=x∗x+y∗y ; i f (R<r ) r=R ; } e l s e {
i f ( i >=0 && i < 2 ) t u r n ( i +1, j , x0+L+z , y , x0+L−x , x0+L , y0 , H,W, L ) ;
i f ( j >=0 && j < 2 ) t u r n ( i , j +1 , x , y0+W+z , y0+W−y , x0 , y0+W, L , H,W) ;
i f ( i <=0 && i >−2) t u r n ( i −1, j , x0−z , y , x−x0 , x0−H, y0 , H,W, L ) ;
i f ( j <=0 && j >−2) t u r n ( i , j −1 , x , y0−z , y−y0 , x0 , y0−H, L , H,W) ;
}
}

int main ( ) {
while ( c i n >> L >> W >> H >> x1 >> y1 >> z1 >> x2 >>y2 >> z2 ) {
i f ( z1 !=0 && z1 !=H) i f ( y1 = = 0 | | y1==W)
{ s t d : : swap ( y1 , z1 ) ; s t d : : swap ( y2 , z2 ) ; s t d : : swap (W,H ) ; } e l s e
{ s t d : : swap ( x1 , z1 ) ; s t d : : swap ( x2 , z2 ) ; s t d : : swap (L ,H ) ; }
i f ( z1==H) z1 =0, z2=H−z2 ;
r=0 x 3 f f f f f f f ; t u r n ( 0 , 0 , x2−x1 , y2−y1 , z2 ,−x1 ,−y1 , L ,W,H ) ;
cout<<r<<e n d l ;
}
return 0 ;
}

6.6 Calculate Expression


char expr [MAX+ 1 ] ; int next [MAX] , s t a c k [MAX] , top ;
double c a l c ( int L , int R ) ;

void p r e f i x ( ) {
int i ; top =−1;
fo r ( i = 0 ; expr [ i ]; ++ i ) {
next [ i ]= −1;
i f ( expr [ i ]== ’ ( ’ ) s t a c k [++top ]= i ;
e l s e i f ( expr [ i ]== ’ ) ’ ) next [ s t a c k [ top −−]]= i ;
}
}

59
double getnum ( int &L ) {
double r e s = 0 ;
i f ( expr [ L]== ’ ( ’ ) { r e s=c a l c (L+1 , next [ L ] − 1 ) ; L=next [ L ] + 1 ; }
e l s e while ( i s d i g i t ( expr [ L ] ) ) r e s=r e s ∗10+ expr [ L++]− ’ 0 ’ ;
return r e s ;
}

void p r o c e s s ( double &a , double b , char op ) {


switch ( op ) {
case ’+ ’ : a += b ; break ;
case ’− ’ : a −= b ; break ;
case ’ ∗ ’ : a ∗= b ; break ;
default : a /= b;
}
}

double c a l c ( int L , int R) {


double a , b , c ;
char op1 , op2 ;
i f ( next [ L] == R ) return c a l c (L+1 , R−1);
a = 0 ; op1 = ( expr [ L]== ’− ’ ? ’− ’ : ’+ ’ ) ;
L = ( expr [ L]== ’+ ’ | | expr [ L]== ’− ’ ? L + 1 : L ) ;
fo r ( b = getnum (L ) ; L<R ; ) {
op2=expr [ L++]; c=getnum (L ) ;
i f ( op2==’+ ’ | | op2==’− ’ | | op1==’ ∗ ’ | | op1==’ / ’ ) {
p r o c e s s ( a , b , op1 ) ; b=c ; op1=op2 ;
} e l s e p r o c e s s ( b , c , op2 ) ;
}
p r o c e s s ( a , b , op1 ) ;
return a ;
}

void main ( ) {
s c a n f ( ”%s ” , expr ) ; p r e f i x ( ) ;
p r i n t f ( ” %.10 l f \n” , c a l c ( 0 , s t r l e n ( expr ) ) ) ;
}

6.7 Cartesian Tree


int l s o n [ maxn ] , r s o n [ maxn ] , pnt [ maxn ] , r o o t , n ;

void B u i l d C a r t e s i a n T r e e ( int a [ ] , int n )


{
int i , j ;
fo r ( i = 0 ; i <n ; j=i ++) {
pnt [ i ]= i − 1 ; l s o n [ i ]= r s o n [ i ]= −1; j=i ;
while ( pnt [ j ]>=0 && a [ i ]>a [ pnt [ j ] ] ) j = pnt [ j ] ;
i f ( j != i ) { pnt [ i ]= pnt [ j ] ; l s o n [ i ]= j ; pnt [ j ]= i ; } ;
i f ( pnt [ i ] >=0) r s o n [ pnt [ i ] ] = i ;
}
fo r ( i =0; i <n ; i ++) i f ( pnt [ i ] < 0 ) r o o t=i ;
}

60
6.8 Catalan Number Generator

\ \ Catalan [ 1 9 ] = 1 7 6 7 2 6 3 1 9 0 < 2ˆ31


\ \ Catalan [ 3 5 ] = 3 1 1 6 2 8 5 4 9 4 9 0 7 3 0 1 2 6 2 < 2ˆ63
\ \ Catalan [ 1 0 0 ] = 8 9 6 5 1 9 9 4 7 0 9 0 1 3 1 4 9 6 6 8 7 1 7 0 0 7 0 0 7 4 1 0 0 6 3 2 4 2 0 8 3 7 5 2 1 5 3 8 7 4 5 9 0 9 3 2 0

#define maxn 1 0 0 0
#define maxlen 7 0 0
#define maxpnum 4 0 0

int prime [ maxpnum ] , primepos [ maxn ∗ 2 ] , num [ maxpnum ] , pnum ;

struct HP{ int l e n ; int s [ maxlen ] ; } ;

void PrintHP (HP x ) { for ( int i=x . l e n ; i > 0 ; i −−) cout<<x . s [ i ] ; }

void Multi (HP &x , int k )


{
int i ; f o r ( i =1; i<=x . l e n ; i ++) x . s [ i ]∗=k ;
x . l e n +=8; // l o g ( 1 0 , maxn ∗ 2 ) ;
fo r ( i =1; i<=x . l e n ; i ++) { x . s [ i +1]+=x . s [ i ] / 1 0 ; x . s [ i ]%=10; }
while ( x . l e n >1 && !x . s [ x . l e n ] ) x . l e n −−;
}

void F a c t o r i z e ( int x , int f l a g )


{
fo r ( int i = 0 ; prime [ i ] ∗ prime [ i ]<=x ; i ++)
while ( x%prime [ i ] = = 0 ) { x/=prime [ i ] ; num [ i ]+= f l a g ; }
i f ( x >1) num [ primepos [ x]]+= f l a g ;
}

HP Catalan ( int n )
{
HP x ; memset(&x , 0 , s i z e o f ( x ) ) ; x . l e n = 1 ; x . s [ 1 ] = 1 ;
memset (num, 0 , s i z e o f (num ) ) ; int i , j ;
fo r ( i =1; i<=n ; i ++) { F a c t o r i z e ( 2 ∗ n+1− i , 1 ) ; F a c t o r i z e ( i , − 1 ) ; }
F a c t o r i z e ( n+1 , −1);
fo r ( i =0; i <pnum ; i ++) while (num [ i ]−−>0) Multi ( x , prime [ i ] ) ;
return x ;
}

void I n i t P r i m e s ( )
{
int i , j ; pnum= 0 ; memset ( primepos , 0 , s i z e o f ( primepos ) ) ;
fo r ( i =2; i<=maxn ∗ 2 ; i ++) i f ( ! primepos [ i ] ) {
primepos [ i ]=pnum ; prime [ pnum++]= i ;
f o r ( j=i+i ; j<=maxn ∗ 2 ; j+=i ) primepos [ j ]= −1;
}
}

void main ( )
{
I n i t P r i m e s ( ) ; int n ;
while ( c i n >>n ) { PrintHP ( Catalan ( n ) ) ; cout<<e n d l ; }
}

61
6.9 Coloring Regular Polygon
Coloring regular n-vertex polygon with m white and n − m black. When n = 17 and m = 8 OUTPUT : 750
int c [ maxn ] [ maxn ] , ans , n , m;

int gcd ( int i , int j ) { i f ( j ==0) return i ; e l s e return gcd ( j , i%j ) ; }

int main ( )
{
c i n >>n>>m;
int i , j , k , l , d ;
c [0][0]=1;
fo r ( i = 1 ; i <maxn ; i ++) {
c [ i ][0]=1;
f o r ( j = 1 ; j<=i ; j ++) c [ i ] [ j ]= c [ i − 1 ] [ j ]+ c [ i − 1 ] [ j − 1 ] ;
}
fo r ( k=0;k<m; k++) {
d=gcd (m, k ) ;
i f ( n∗d % m = = 0 ) { l=n∗d/m; ans+=c [ l − 1 ] [ d − 1 ] ; }
}
i f (m%2==0) {
i f ( n%2==0) ans+=(m/ 2 ) ∗ c [ n /2 −1][m/2 −1];
i f (m==2) ans+=(m/ 2 ) ∗ ( n − 1 ) ; e l s e
f o r ( i =2−n %2; i<=n−(m− 2 ) ; i +=2)
ans+=(m/ 2 ) ∗ ( i −1)∗ c [ ( n−i ) / 2 − 1 ] [ (m−2)/2 −1];
} e l s e f o r ( i =2−n %2; i<=n−(m− 1 ) ; i +=2) ans+=m∗ c [ ( n−i ) / 2 − 1 ] [ (m−1)/2 −1];
cout<<ans / ( 2 ∗m)<<e n d l ;
return 0 ;
}

6.10 Counting Inverse Pairs


#include<i o s t r e a m . h>
#include<f s t r e a m . h>
#include<a l g o r i t h m >

#define maxn 1 0 0 0 0
int a [ maxn ] , t [ maxn ] , n , ans ;

void s o r t ( int b , int e )


{
i f ( e−b<=0) return ;
int mid=(b+e ) / 2 , p1=b , p2=mid+1, i=b ;
s o r t ( b , mid ) ; s o r t ( mid+1, e ) ;
while ( p1<=mid | | p2<=e )
i f ( p2>e | | ( p1<=mid && a [ p1]<=a [ p2 ] ) ) t [ i ++]=a [ p1 ++];
e l s e { t [ i ++]=a [ p2 ++]; ans+=mid−p1 + 1 ; }
fo r ( i=b ; i<=e ; i ++)a [ i ]= t [ i ] ;
}

int main ( )
{
ifstream cin ( ” input . txt ” ) ;
int i , j ;
while ( c i n >>n ) {
f o r ( i =0; i <n ; i ++) c i n >>a [ i ] ;
ans = 0 ; s o r t ( 0 , n − 1 ) ; // Counting I n v e r s e Number
cout<<”Minimum exchange o p e r a t i o n s : ”<<ans<<e n d l ;
}
return 0 ;
}
62
6.11 Counting Trees
// Rooted {1 , 5 , 11 , 20 , 30} = > {1 , 9 , 1842 , 12826228 , 354426847597 }
// Non−Rooted { 1 , 3 , 1 0 , 2 5 , 3 0 } = > { 1 , 1 , 1 0 6 , 1 0 4 6 3 6 8 9 0 , 14830871802 }
void main ( )
{
ifstream cin ( ” input . txt ” ) ;
int i , j , n ;
memset ( s , 0 , s i z e o f ( s ) ) ; a [ 0 ] = 0 ; a [ 1 ] = 1 ;
fo r ( i = 1 ; i <maxn− 1 ; i ++)
{
a [ i +1] = 0;
f o r ( j = 1 ; j<=i ; j ++)
{
s [ i ] [ j ] = s [ i −j ] [ j ] + a [ i +1−j ] ;
a [ i +1] += j ∗a [ j ] ∗ s [ i ] [ j ] ;
}
a [ i +1] /= i ;
}
while ( c i n >>n ) // a [ n ] = Rooted ; ans = Non−Rooted
{
int ans = a [ n ] ;
f o r ( i = 1 ; 2 ∗ i<=n ; i ++) ans −= a [ i ] ∗ a [ n−i ] ;
i f ( n%2==0 ) ans += ( a [ n / 2 ] + 1 ) ∗ a [ n / 2 ] / 2 ;
c o u t << a [ n] < < ” ” << ans << e n d l ;
}
}

6.12 Eight Puzzle Problem


Input: 012345678 123456780 Output: ST EP = 22

Common Part

#define maxlen 1 0
#define s i z e 362880+1

const int l i n k [ 9 ] [ 5 ] = { { 2 , 1 , 3 } , { 3 , 0 , 2 , 4 } , { 2 , 1 , 5 } , { 3 , 0 , 4 , 6 } ,
{4 ,1 ,3 ,5 ,7} , {3 ,2 ,4 ,8} , {2 ,3 ,7} , {3 ,4 ,6 ,8} , {2 ,5 ,6} };

int s [ maxlen ] , p [ maxlen ] , mk [ s i z e ] , open [ s i z e ] , cur , t a i l ;

void encode ( int ∗ s , int l e n , int &x )


{
int i , j , k , l ; for ( x=0, i=l e n − 1 ; i >=0; x+=k∗p [ i −−])
fo r ( k=s [ i ] , j=i + 1 ; j <l e n ; j ++) i f ( s [ j ]< s [ i ] ) k−−;
}

void decode ( int ∗ s , int l e n , int x )


{
int i , j , k , l ; for ( i=l e n − 1 ; i >=0; i −−){ s [ i ]=x/p [ i ] ; x%=p [ i ] ; }
fo r ( i = 0 ; i <l e n ; i ++) for ( j = 0 ; j <i ; j ++) i f ( s [ j ]>=s [ i ] ) s [ j ]++;
}

void p r i n t ( int ∗ s , int l e n )


{
f o r ( int i =0; i <l e n ; i ++)
cout<<s [ i ] ;
cout<<e n d l ;
}

63
int main ( )
{
ifstream cin ( ” input . txt ” ) ;
char ch ; int i , s r c , d s t ;
fo r ( p [ 0 ] = i = 1 ; i <maxlen ; i ++) p [ i ]=p [ i −1]∗ i ;
fo r ( i =0; i <9; i ++) { c i n >>ch ; s [ i ]=ch− ’ 0 ’ ; } encode ( s , 9 , s r c ) ;
fo r ( i =0; i <9; i ++) { c i n >>ch ; s [ i ]=ch− ’ 0 ’ ; } encode ( s , 9 , d s t ) ;
s o l v e ( s r c , d s t ) ; cout<<cur<<” ”<<t a i l <<e n d l ;
return 0 ;
}

Simple Breadth First Search

void output ( int pos , int num)


{
i f ( pos ==1) cout<<” T o t a l number o f s t e p s = ”<<num<<e n d l ;
e l s e output (mk [ open [ pos ] ] , num+1);
decode ( s , 9 , open [ pos ] ) ; p r i n t ( s , 9 ) ;
}

void s o l v e ( int s r c , int d s t )


{
int i , j , k , x , l , ps ;
i f ( s r c==d s t ) { cout<<”SRC DST i s t h e same ! ”<<e n d l ; return ; }
c u r = 0 ; t a i l = 1 ; open [ 1 ] = s r c ; mk [ s r c ] = 1 ;
while(++cur<=t a i l ) {
decode ( s , 9 , open [ c u r ] ) ; for ( ps = 0 ; s [ ps ] ; ps ++);
f o r ( k = 1 ; k<=l i n k [ ps ] [ 0 ] ; k++) {
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ; encode ( s , 9 , x ) ;
i f ( ! mk [ x ] ) {
mk [ x]= c u r ; open[++ t a i l ]=x ;
i f ( x==d s t ) { output ( t a i l , 0 ) ; return ; }
}
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ;
}
}
cout<<”No s o l u t i o n ! ”<<e n d l ;
}
Heuristic Breadth First Search

int d [ s i z e ] , heap [ s i z e ] , hlen , h [ s i z e ] , d s t s [ maxlen ] ;


int cmp( const int & i , const int & j ) { return h [ i ]>h [ j ] ; }

void c a l c h ( int pos )


{
int i , j , k ; h [ pos ]=d [ pos ] ;
fo r ( i =0; i <9; i ++) i f ( s [ i ] ! = d s t s [ i ] ) h [ pos ]++;
}

void output ( int pos , int num)


{
i f ( pos ==1) cout<<” T o t a l number o f s t e p s = ”<<num<<e n d l ;
e l s e output (mk [ open [ pos ] ] , num+1);
decode ( s , 9 , open [ pos ] ) ; p r i n t ( s , 9 ) ;
}

64
void s o l v e ( int s r c , int d s t )
{
int i , j , k , x , l , ps ;
i f ( s r c==d s t ) { cout<<”SRC DST i s t h e same ! ”<<e n d l ; return ; }
t a i l = 1 ; open [ 1 ] = s r c ; mk [ s r c ] = 1 ; h l e n = 1 ; heap [ 0 ] = 1 ; d [ 1 ] = 0 ;
decode ( s , 9 , s r c ) ; decode ( d s t s , 9 , d s t ) ; c a l c h ( 1 ) ;
while ( hlen >0){
c u r=heap [ 0 ] ; s t d : : pop heap ( heap , heap+( hlen −−),cmp ) ;
decode ( s , 9 , open [ c u r ] ) ; for ( ps = 0 ; s [ ps ] ; ps ++);
f o r ( k = 1 ; k<=l i n k [ ps ] [ 0 ] ; k++) {
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ; encode ( s , 9 , x ) ;
i f ( ! mk [ x ] ) {
mk [ x]= c u r ; open[++ t a i l ]=x ; d [ t a i l ]=d [ c u r ] + 1 ; c a l c h ( t a i l ) ;
heap [ h l e n++]= t a i l ; s t d : : push heap ( heap , heap+hlen , cmp ) ;
i f ( x==d s t ) { output ( t a i l , 0 ) ; return ; }
}
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ;
}
}
cout<<”No s o l u t i o n ! ”<<e n d l ;
}

Double Breadth First Search

int s t e p , d i [ s i z e ] ;

void out1 ( int pos )


{
i f ( pos >2) out1 (mk [ open [ pos ] ] ) ; s t e p ++;
decode ( s , 9 , open [ pos ] ) ; p r i n t ( s , 9 ) ;
}

void out2 ( int pos )


{
decode ( s , 9 , open [ pos ] ) ; p r i n t ( s , 9 ) ;
i f ( pos >2) out2 (mk [ open [ pos ] ] ) ; s t e p ++;
}

void s o l v e ( int s r c , int d s t )


{
int i , j , k , x , l , ps ;
i f ( s r c==d s t ) { cout<<”SRC DST i s t h e same ! ”<<e n d l ; return ; }
open [ 1 ] = s r c ; mk [ s r c ] = 1 ; d i [ s r c ] = 1 ; c u r =0;
open [ 2 ] = d s t ; mk [ d s t ] = 2 ; d i [ d s t ] = 2 ; t a i l =2;
while(++cur<=t a i l ) {
decode ( s , 9 , open [ c u r ] ) ; for ( ps = 0 ; s [ ps ] ; ps ++);
f o r ( k = 1 ; k<=l i n k [ ps ] [ 0 ] ; k++) {
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ; encode ( s , 9 , x ) ;
i f ( ! mk [ x ] ) { mk [ x]= c u r ; open[++ t a i l ]=x ; d i [ x]= d i [ open [ c u r ] ] ; }
e l s e i f ( d i [ x ] ! = d i [ open [ c u r ] ] ) {
s t e p =0;
i f ( d i [ x ] = = 1 ) { out1 (mk [ x ] ) ; out2 ( c u r ) ; }
else { out1 ( c u r ) ; out2 (mk [ x ] ) ; }
cout<<” T o t a l number o f s t e p s = ”<<s t e p <<e n d l ;
return ;
}
s t d : : swap ( s [ ps ] , s [ l i n k [ ps ] [ k ] ] ) ;
}
}
cout<<”No s o l u t i o n ! ”<<e n d l ;
}

65
6.13 Extended Honai Tower
int P [ML ] [ ML] ,D[ML ] [ ML] ,T[ML ] [ ML ] ;

void i n i t ( )
{
int i , j , x , k , l ;
fo r (P [ 0 ] [ 0 ] = l =1; l <ML; l ++) {
P [ 0 ] [ l ] = P[ l ] [ 0 ] = 1 ;
f o r ( i =1; i <l ; i ++) P [ i ] [ l −i ] = P [ i − 1 ] [ l −i ]+P [ i ] [ l −i − 1 ] ;
}
fo r ( i =0; i <ML; i ++) for ( k=j = 0 ; j <ML−i && k!=ML; j ++)
f o r ( x=0;x<P [ i ] [ j ] ; x ++) { i f ( k==ML) break ; D[ i ] [ k++] = 1<< j ; }
fo r ( i =0; i <ML; i ++) T[ i ] [ 0 ] = 0 ;
fo r ( j =1; j <ML; j ++) for ( i =0; i <20; i ++) T [ i ] [ j ] = T [ i ] [ j −1]+D[ i ] [ j − 1 ] ;
}

int main ( )
{
init ();
fo r ( int a , b , c a s e c = 1 ; c i n >>a>>b && ( a | | b ) ; c a s e c++)
c o u t << ” Case ” << c a s e c << ” : ” << T [ b − 3 ] [ a ] < < e n d l ;
return 0 ;
}

6.14 High Precision Square Root


int x [ maxlen ] , y [ maxlen ] , z [ maxlen ] , bck [ maxlen ] , lx , ly , l z ;

int I s S m a l l e r ( ) // i s z<=y ?
{ int i=l y ; while ( i >1 && z [ i ]==y [ i ] ) i −−; return ( z [ i ]<=y [ i ] ) ; }

void S o l v e ( ) // yˆ2=x
{
int i , j , k ;
l x =( l y + 1 ) / 2 ; l y=l x ∗ 2 ;
memset ( x , 0 , s i z e o f ( x ) ) ; memset ( z , 0 , s i z e o f ( z ) ) ;
fo r ( i=l x ; i >0; i −−){
f o r ( j = 1 ; j < 1 0 ; x [ i ]= j ++){
memcpy( bck , z , s i z e o f ( z ) ) ;
z [ 2 ∗ i −1]++; for ( k=i ; k<=l x ; k++)
{ z [ i −1+k]+=2∗x [ k ] ; z [ i+k]+=z [ i −1+k ] / 1 0 ; z [ i −1+k ]%=10; }
f o r ( k=l x+i ; k<=l y ; k++){ z [ k+1]+=z [ k ] / 1 0 ; z [ k ]%=10; }
i f ( ! I s S m a l l e r ( ) ) break ;
};
i f ( j <10) memcpy( z , bck , s i z e o f ( bck ) ) ;
};
fo r ( i=l x ; i >0; i −−) cout<<x [ i ] ; cout<<e n d l ;
}

int main ( )
{
char ch , s [ maxlen ] ; int i , j ;
memset ( y , 0 , s i z e o f ( y ) ) ;
c i n >>s ; l y=s t r l e n ( s ) ;
fo r ( i =0; i <l y ; i ++) y [ i +1]= s [ ly −1− i ]− ’ 0 ’ ;
Solve ( ) ;
return 0 ;
}

66
6.15 Largest Empty Rectangle
O(N 2 )

int n , wx , wy , x [ maxn ] , y [ maxn ] , i d [ maxn ] ;


int xx [ maxn ] , yy [ maxn ] , ans ;

bool cmp( const int&i , const int&j )


{
return x [ i ]<x [ j ] ;
}

void c a l c ( int i , int px , int py )


{
int r e t , j , low =0, h i g h=wy ;
fo r ( ; i <n ; i ++) i f ( x [ i ]>px )
{
j =(high−low ) ∗ ( x [ i ]−px ) ; i f ( j >ans ) ans=j ;
i f ( y [ i ]<py && y [ i ]>=low ) low = y [ i ] ;
i f ( y [ i ]>=py && y [ i ]<=h i g h ) h i g h = y [ i ] ;
}
}

int main ( )
{
int i , j , k ;
c i n >>wx>>wy>>n ; for ( i =0; i <n ; i ++) c i n >>x [ i ]>>y [ i ] ;
x [ n]=y [ n ] = 0 ; n++; x [ n]=wx ; y [ n]=wy ; n++;
fo r ( i =0; i <n ; i ++) i d [ i ]= i ; s t d : : s o r t ( id , i d+n , cmp ) ;
fo r ( i =0; i <n ; i ++) { xx [ i ]=x [ i d [ i ] ] ; yy [ i ]=y [ i d [ i ] ] ; }
fo r ( i =0; i <n ; i ++) { x [ i ]=xx [ i ] ; y [ i ]=yy [ i ] ; }
s t d : : s o r t ( yy , yy+n ) ; k=s t d : : unique ( yy , yy+n)−yy ;
ans =0;
fo r ( i =0; i <n ; i ++) c a l c ( i , x [ i ] , y [ i ] ) ;
fo r ( j =0; j <k ; j ++) c a l c ( 0 , 0 , yy [ j ] ) ;
cout<<ans<<e n d l ;
return 0 ;
}
O(D2 )

int x [ maxn ] , y [ maxn ] , x l i s t [ maxn ] , y l i s t [ maxn ] , nx , ny , ans , n , wx , wy ;


char g [ maxd ] [ maxd ] ; int u [ maxd ] , d [ maxd ] , l [ maxd ] ;

int main ( )
{
int i , j , px , py , up , down , tmp ; ans =0;
c i n >>wx>>wy>>n ; for ( i =0; i <n ; i ++) c i n >>x [ i ]>>y [ i ] ;
nx=ny=n ; f or ( i =0; i <n ; i ++) { x l i s t [ i ]=x [ i ] ; y l i s t [ i ]=y [ i ] ; }
x l i s t [ nx++]= y l i s t [ ny++]=0; x l i s t [ nx++]=wx ; y l i s t [ ny++]=wy ;
s t d : : s o r t ( x l i s t , x l i s t+nx ) ; nx=s t d : : unique ( x l i s t , x l i s t +nx)− x l i s t ;
s t d : : s o r t ( y l i s t , y l i s t+ny ) ; ny=s t d : : unique ( y l i s t , y l i s t +ny)− y l i s t ;

fo r ( i = 0 ; i <nx ; i ++) memset ( g , 0 , n ) ;

fo r ( i = 0 ; i <n ; i ++)
{
px = s t d : : lower bound ( x l i s t , x l i s t+nx , x [ i ] ) − x l i s t ;
py = s t d : : lower bound ( y l i s t , y l i s t+ny , y [ i ] ) − y l i s t ;
g [ px ] [ py ] = 1 ;
}

67
fo r ( j = 0 ; j <ny − 1 ; j ++)
{
tmp = wx ∗ ( y l i s t [ j +1] − y l i s t [ j ] ) ;
i f ( tmp > ans ) ans = tmp ;
}
fo r ( i = 1 ; i <nx ; i ++)
{
down = 0 ; up=ny −1;
f o r ( j = 0 ; j <ny ; j ++) i f ( i = = 1 | | ∗ ( ∗ ( g+i −1)+ j ) )
{ l [ j ]= i − 1 ; d [ j ] = 0 ; down=j ; } e l s e
i f ( down > d [ j ] ) d [ j ] = down ;
f o r ( j=ny − 1 ; j >=0; j −−)
{
i f ( i = = 1 | | ∗ ( ∗ ( g+i −1)+ j ) ) { u [ j ]=ny − 1 ; up=j ; } e l s e
i f ( up < u [ j ] ) u [ j ] = up ;
tmp = ( x l i s t [ i ] − x l i s t [ l [ j ] ] ) ∗ ( y l i s t [ u [ j ]] − y l i s t [ d [ j ] ] ) ;
i f ( tmp>ans ) ans=tmp ;
}
}
cout<<ans<<e n d l ;
return 0 ;
}

O(N 2 )

int n , wx , wy , i d [ maxn ] , x [ maxn ] , y [ maxn ] , ans , xx [ maxn ] , yy [ maxn ] ;

bool xcmp ( const int&i , const int & j ) { return x [ i ]<x [ j ] ; }


bool ycmp ( const int&i , const int & j ) { return y [ i ]<y [ j ] ; }

int main ( )
{
int i , j , k , l , tmp , low , high , l a s t ;
c i n >>wx>>wy>>n ; for ( i =0; i <n ; i ++) c i n >>x [ i ]>>y [ i ];
x [ n]=y [ n ] = 0 ; n++; x [ n]=wx ; y [ n]=wy ; n++;
fo r ( i =0; i <n ; i ++) i d [ i ]= i ;
s t d : : s o r t ( id , i d+n , xcmp ) ;
fo r ( i =0; i <n ; i ++) { xx [ i ]=x [ i d [ i ] ] ; yy [ i ]=y [ i d [ i ]]; }
fo r ( i =0; i <n ; i ++) { x [ i ]=xx [ i ] ; y [ i ]=yy [ i ] ; }
s t d : : s o r t ( id , i d+n , ycmp ) ;
fo r ( i =0; i <n ; i ++)
{
l = 0 ; l a s t =0;
f o r ( j =0; j <n ; j ++) i f ( x [ i d [ j ]] < x [ i ] && y [ i d [ j ]] > l a s t )
{
i f ( y [ i d [ j ]] − l a s t > l ) l=y [ i d [ j ]] − l a s t ;
l a s t=y [ i d [ j ] ] ;
}
i f ( wy−l a s t >l ) l=wy−l a s t ;
i f ( l ∗x [ i ] > ans ) ans = l ∗x [ i ] ;
low = 0 ; h i g h=wy ; for ( j=i +1; j <n ; j ++)
{
tmp = ( high−low ) ∗ ( x [ j ]−x [ i ] ) ;
i f ( tmp> ans ) ans=tmp ;
i f ( y [ j ]>=y [ i ] && y [ j ]< h i g h ) h i g h = y [ j ];
i f ( y [ j ]<=y [ i ] && y [ j ]> low ) low = y [ j ];
}
}
cout<<ans<<e n d l ;
return 0 ;
}

68
6.16 Last Non-Zero Digit of N!
Smart Edition

const int f f [ 1 0 ] = { 1 , 1 , 2 , 6 , 4 , 4 , 4 , 8 , 4 , 6 } ;

int f a c t ( int n )
{
int i , x ;
i f ( n <5) return f f [ n ] ;
x = ( f f [ n%10] ∗ 6 ) %10;
fo r ( i = 1 ; i <=(n / 5 ) % 4 ; i ++)
i f ( x = = 6 | | x ==2 ) x=(x + 1 0 ) / 2 ; e l s e x /=2;
return ( f a c t ( n / 5 ) ∗ x ) % 1 0 ;
}

High Precision Edition

int a [ 1 0 ] = { 6 , 1 , 2 , 6 , 4 , 4 , 4 , 8 , 4 , 6 } ;
int b [ 4 ] = { 1 , 8 , 4 , 2 } ;

void d i v i d e ( char s [ ] , int & l e n )


{
int i ;
char temp [ 2 0 0 ] ;
fo r ( i = 0 ; i <l e n ; i ++) temp [ i ] = s [ i ] ∗ 2 ; temp [ l e n ] = 0 ;
fo r ( i = 0 ; i <l e n ; i ++) i f ( temp [ i ] > 9 ) { temp [ i ] −=10; temp [ i +1]++; }
fo r ( i = 0 ; i <l e n ; i ++) s [ i ] = temp [ i + 1 ] ;
i f ( temp [ l e n ] = = 0 ) l e n −−;
}

int f a c t ( char s [ ] )
{
int r e s u l e n t =1, power =0, l e n=s t r l e n ( s ) , i ;
char temp ;
i f ( l e n==1&&s [0]== ’ 0 ’ ) return 1 ;
fo r ( i =0; i <l e n ; i ++) s [ i ]−= ’ 0 ’ ;
fo r ( i =0; i <l e n / 2 ; i ++){ temp=s [ i ] ; s [ i ]= s [ l e n −1− i ] ; s [ l e n −1− i ]=temp ; }
while ( l e n ) {
r e s u l e n t=r e s u l e n t ∗ a [ s [ 0 ] % 1 0 ] % 1 0 ;
divide ( s , len ) ;
power+=(s [ 1 ] ∗ 1 0 + s [ 0 ] ) % 4 ;
}
r e s u l e n t=r e s u l e n t ∗b [ power %4]%10;
return r e s u l e n t ;
}

6.17 Least Common Ancestor


int n , h , r o o t ; // maxh−1 = h = f l o o r ( l o g ( 2 , n − 1 ) )
int pnt [ maxn ] [ maxh ] , son [ maxn ] , next [ maxn ] , depth [ maxn ] ;
int s t a c k [ maxn ] , mylog [ maxn ] ;

int GetParent ( int x , int l e n )


{
while ( l e n > 0 ) {
x = pnt [ x ] [ mylog [ l e n ] ] ;
l e n −= ( 1<<mylog [ l e n ] ) ;
}
return x ;
}

69
int LCA( int x , int y ) // O( l o g N )
{
int nx , ny , px , py , low , mid , h i g h ;
low = 0 ; h i g h = depth [ x]< depth [ y ] ? depth [ x ] : depth [ y ] ;
px = GetParent ( x , depth [ x]− h i g h ) ;
py = GetParent ( y , depth [ y]− h i g h ) ;
i f ( px == py ) return px ;
while ( high−low >1)
{
mid = mylog [ high−low − 1 ] ;
nx = pnt [ px ] [ mid ] ;
ny = pnt [ py ] [ mid ] ;
mid = h i g h − (1<<mid ) ;
i f ( nx == ny ) low = mid ; e l s e { h i g h = mid ; px = nx ; py = ny ; }
}
return pnt [ px ] [ mylog [ high−low ] ] ;
}

int LCA 2 ( int x , int y ) // O( l o g ˆ 2 N )


{
int low , mid , h i g h ;
low = 0 ; mid = h i g h = depth [ x]< depth [ y ] ? depth [ x ] : depth [ y ] ;
i f ( GetParent ( x , depth [ x]−mid ) ! = GetParent ( y , depth [ y]−mid ) )
while ( low+1<h i g h )
{
mid = ( low + h i g h ) / 2 ;
i f ( GetParent ( x , depth [ x]−mid ) ! = GetParent ( y , depth [ y]−mid ) )
h i g h = mid ; e l s e low = mid ;
} e l s e low = h i g h ;
return GetParent ( x , depth [ x]− low ) ;
}

void d f s ( int d , int c u r )


{
int i , j ; s t a c k [ d ] = c u r ; depth [ c u r ] = d ;
fo r ( j =1, i = 2 ; i<=d ; j ++, i ∗ = 2 ) pnt [ c u r ] [ j ]= s t a c k [ d−i ] ;
fo r ( j=son [ c u r ] ; j ; j=next [ j ] ) d f s ( d +1 , j ) ;
}

void main ( )
{
int i , j , k , l ;
fo r ( i =0, j = 1 ; j <maxn ; i ++)
{
k = j ∗ 2 ; i f ( k>maxn ) k = maxn ;
while ( j <k ) mylog [ j ++] = i ;
}
c i n >>n ;
fo r ( i = 1 ; i<=n ; i ++) {
son [ i ] = next [ i ] = 0 ;
f o r ( j = 0 ; j<=h ; j ++) pnt [ i ] [ j ] = 0 ;
}
fo r ( i = 1 ; i <n ; i ++) {
c i n >> j >> k ; pnt [ j ] [ 0 ] = k ;
next [ j ]= son [ k ] ; son [ k]= j ;
}
fo r ( i = 1 ; i<=n ; i ++) i f ( pnt [ i ] [ 0 ] = = 0 ) { r o o t=i ; break ; } ;

dfs ( 0 , root ) ; // P r e p r o c e s s Parent Array

fo r ( c i n >>k ; k ; k − −) { c i n >> i >> j ; c o u t << LCA( i , j ) << e n d l ; }


}

70
6.18 Longest Common Substring
O(N log N ), using Suffix Sort with LCP information

int LCS( char ∗ s1 , int l 1 , char ∗ s2 , int l 2 , int & i 1 , int & i 2 )
{
strcpy ( s , s1 ) ; s [ l 1 ]= ’ $ ’ ;
s t r c p y ( s+l 1 +1 , s 2 ) ; n=l 1+l 2 +1;
SuffixSort ( ) ; GetHeight ( ) ; // s [ l 1 ] = 0 ;
int i , j , l = 0 ; i 1 = i 2 = 0 ;
fo r ( i = 1 ; i <n ; i ++)
{
i f ( h e i g h t [ i ]>= l && i d [ i −1]< l 1 && i d [ i ]> l 1 )
{ l = h e i g h t [ i ] ; i 1 = i d [ i − 1 ] ; i 2 = i d [ i ]− l 1 − 1 ; }
i f ( h e i g h t [ i ]>= l && i d [ i ]< l 1 && i d [ i −1]> l 1 )
{ l = height [ i ] ; i1 = id [ i ] ; i 2 = i d [ i −1]− l 1 − 1 ; }
}
return l ;
}
O(N 2 ), using KMP

int LCS( char ∗ s1 , int l 1 , char ∗ s2 , int l 2 , int & a n s i , int & a n s j )
{
int i , j , k , l , ans = 0 ; a n s i = 0 ; a n s j =0;
fo r ( i = 0 ; i <l 1 −ans ; i ++)
{
m a k e f a i l ( s 1+i , l 1 −i ) ;
kmp ( s2 , l 2 , s 1+i , l 1 −i , 0 , l , j ) ;
i f ( l >ans ) { ans=l ; a n s i=i ; a n s j=j ; }
}
return ans ;
}
Example Part

char s 1 [ maxlen ] , s 2 [ maxlen ] ; int l 1 , l 2 ;

int main ( )
{
ifstream cin ( ” input . txt ” ) ;
c i n >>s1>>s 2 ; l 1=s t r l e n ( s 1 ) ; l 2=s t r l e n ( s 2 ) ;
int i 1 , i 2 , i , l = LCS( s1 , l 1 , s2 , l 2 , i 1 , i 2 ) ;
cout<<l <<” ”<<i 1 <<” ”<<i 2 <<e n d l ;
fo r ( i =0; i <l ; i ++) cout<<s 1 [ i 1+i ] ; cout<<e n d l ;
fo r ( i =0; i <l ; i ++) cout<<s 2 [ i 2+i ] ; cout<<e n d l ;
return 0 ;
}
M th Longest Common Substring

#define h next // h [ i ] = L o n g e s t Common S u b s t r i n g o f s1 +0 and s2+i


int mk [ maxn ] ; // a l r e a d y found a common s u b s t r i n g = s2 [ i . . mk [ i ] )
struct CAnswer { int pos , l e n ; } ans [ maxn ] ;

bool newcmp ( const CAnswer &a , const CAnswer &b )


{
i f ( a . l e n ! = b . l e n ) return a . l e n >b . l e n ;
return a . pos<b . pos ;
}

71
void LCS( char ∗ s1 , int l 1 , char ∗ s2 , int l 2 , int m)
{
strcpy ( s , s1 ) ; s [ l 1 ]= ’ $ ’ ;
s t r c p y ( s+l 1 +1 , s 2 ) ; n=l 1+l 2 +1;
SuffixSort ( ) ; GetHeight ( ) ; // s [ l 1 ] = 0 ;
int i , j , k , p , u , v ;
// computing l o n g e s t common p r e f i x b e t w e e n s1 +0 and s2+i
memset ( h , 0 , s i z e o f ( h ) ) ;
fo r ( i = 0 ; i <n ; i ++) i f ( i <n−1 && i d [ i ]< l 1 && i d [ i +1]> l 1 ) {
k=maxlen ;
f o r ( j=i + 1 ; j <n ; j ++)
{ i f ( i d [ j ]< l 1 ) break ; i f ( h e i g h t [ j ]<k ) k=h e i g h t [ j ] ; h [ j ]=k ; }
i=j −1;
}
fo r ( i=n − 1 ; i > 0 ; i −−) i f ( i d [ i ]< l 1 && i d [ i −1]> l 1 ) {
k=maxlen ;
f o r ( j=i − 1 ; j >=0; j −−) {
i f ( i d [ j ]< l 1 ) break ; i f ( h e i g h t [ j +1]<k ) k=h e i g h t [ j + 1 ] ;
i f ( k>h [ j ] ) h [ j ]=k ;
}
i=j +1;
}
num= 0 ; // C o l l e c t Non−P o s i t i o n −C o v e r i n g Answer
fo r ( i =0; i <n ; i ++)
i f ( h [ rank [ i ] ] ! = 0 & & ( i = = 0 | | h [ rank [ i −1]]<=h [ rank [ i ] ] ) )
{ k=rank [ i ] ; ans [ num ] . pos=i d [ k ] ; ans [ num ] . l e n=h [ k ] ; num++;}
s t d : : s o r t ( ans , ans+num , newcmp ) ;
memset (mk, 0 , s i z e o f (mk ) ) ;
fo r ( i=j = 0 ; i <num && j <m; i ++) {
k=rank [ ans [ i ] . pos ] ; // Check Non−S u b s t r i n g −C o v e r i n g
i f ( mk [ k]>=h [ k ] ) continue ;
int ok =1;
f o r ( u=maxlen , p=k + 1 ; p<n ; p++) {
i f ( h e i g h t [ p]<u ) u=h e i g h t [ p ] ;
i f ( u<h [ k ] ) break ;
i f (mk [ p]>=h [ k ] ) { ok = 0 ; break ; }
}
i f ( ! ok ) continue ;
f o r ( u=maxlen , p=k − 1 ; p>=0; p−−) {
i f ( h e i g h t [ p+1]<u ) u=h e i g h t [ p + 1 ] ;
i f ( u<h [ k ] ) break ;
i f (mk [ p]>=h [ k ] ) { ok = 0 ; break ; }
}
i f ( ! ok ) continue ;
j ++; // Check Passed , S e t A l r e a d y Found S u b s t r i n g
f o r ( v = 0 ; v<h [ k ] ; v++)
i f ( mk [ rank [ i d [ k]+v ] ] < h [ k]−v ) mk [ rank [ i d [ k]+v ] ] = h [ k]−v ;
// LENGTH h [ rank [ ans [ i ] . pos ] ] POSITION ans [ i ] . pos−l 1 −1
char ch = s [ ans [ i ] . pos + h [ rank [ ans [ i ] . pos ] ] ] ;
s [ ans [ i ] . pos + h [ rank [ ans [ i ] . pos ] ] ] = 0 ;
c o u t << s+ans [ i ] . pos << e n d l ;
s [ ans [ i ] . pos + h [ rank [ ans [ i ] . pos ] ] ] = ch ;
}
}

72
6.19 Longest Non Descending Sub Sequence
int LNDSS( int a [ ] , int n ) // L o n g e s t Non−d e s c e n d i n g Sub Sequence
{
int i , j , k , ∗ b=new int [ n +1] , ans =0;
b [ ans]=−0 x 3 f 3 f 3 f 3 f ;
fo r ( i =0; i <n ; i ++){ // l o w e r b o u n d f o r Asending Sub Squence
j=s t d : : upper bound ( b , b+ans +1,a [ i ]) −b ;
i f ( j >ans ) b[++ans ]=a [ i ] ; e l s e i f ( a [ i ]<b [ j ] ) b [ j ]=a [ i ] ;
}
delete b ; return ans ;
}

6.20 Join and Disjoin


Note: UnionFind.h contains a Union-Find Set (Section 1.10 on Page 11)
#include<u n i o n f i n d . h>

int Gather ( int x , int y )


{
i f ( ! x && ! y ) return 0 ;
i f ( ! x ) return f i n d ( y ) ;
i f ( ! y ) return f i n d ( x ) ;
Merge ( x , y ) ;
return f i n d ( x ) ;
}

void J o i n ( int x , int y )


{
int a=Gather ( x , y ) ; // x , y n e r v e r be z e r o
int b=Gather ( vs [ x ] , vs [ y ] ) ;
vs [ a]=b ; vs [ b]=a ;
}

void D i s j o i n ( int x , int y )


{
int a=Gather ( x , vs [ y ] ) ;
int b=Gather ( y , vs [ x ] ) ;
vs [ a]=b ; vs [ b]=a ;
}

73
6.21 Magic Square
#define maxn 1 0 0 0
int a [ maxn ] [ maxn ] , n ;

void b u i l d ( int n , int a [ ] [ maxn ] ) // No s o l u t i o n s when n=2!


{
int i , j , k , n2=n∗n ,m=n / 2 ,m2=m∗m;
fo r ( i =0; i <n ; i ++) for ( j =0; j <n ; j ++) a [ i ] [ j ] = 0 ;
i f ( n==2) return ; // No s o l u t i o n s
i f ( n%2==1)
f o r ( i =0, j=n / 2 , k=1;k<=n2 ; k++) {
a[ i ][ j ] = k;
i f ( ! a [ ( i+n−1)%n ] [ ( j +1)%n ] )
{ i =( i+n−1)%n ; j =( j +1)%n ; } e l s e i =( i +1)%n ;
}
e l s e i f ( n%4==0)
f o r ( k=0, i =0; i <n ; i ++) for ( j =0; j <n ; j ++) {
a [ i ] [ j ] = ++k ;
i f ( i%4==j % 4 | | i%4+j %4==3) a [ i ] [ j ] = n2+1−a [ i ] [ j ] ;
}
e l s e i f ( n%4==2)
f o r ( i =0, j=m/ 2 , k=0;k<m2 ; k++) {
i f ( ( i<=m/ 2 & & ! ( i==m/2&& j==m/ 2 ) ) | | ( i==m/2+1&& j==m/ 2 ) ) { // L
a [ i ∗ 2 ] [ j ∗2+1]=k ∗ 4 + 1 ; a [ i ∗ 2 + 1 ] [ j ∗2]= k ∗4+2;
a [ i ∗ 2 + 1 ] [ j ∗2+1]=k ∗ 4 + 3 ; a [ i ∗ 2 ] [ j ∗2]= k ∗4+4;
} e l s e i f ( i >m/ 2 + 1 ) { // X
a [ i ∗ 2 ] [ j ∗2]= k ∗ 4 + 1 ; a [ i ∗ 2 + 1 ] [ j ∗2+1]=k ∗4+2;
a [ i ∗ 2 + 1 ] [ j ∗2]= k ∗ 4 + 3 ; a [ i ∗ 2 ] [ j ∗2+1]=k ∗4+4;
} e l s e { // U
a [ i ∗ 2 ] [ j ∗ 2 ]=k ∗ 4 + 1 ; a [ i ∗ 2 + 1 ] [ j ∗2]= k ∗4+2;
a [ i ∗ 2 + 1 ] [ j ∗2+1]=k ∗ 4 + 3 ; a [ i ∗ 2 ] [ j ∗2+1]=k ∗4+4;
}
i f ( ! a [ ( i+m−1)%m∗ 2 ] [ ( j +1)%m∗ 2 ] ) i =( i+m−1)%m, j =( j +1)%m;
e l s e i =( i +1)%m;
}
}

int main ( )
{
while ( c i n >>n ) {
b u i l d ( n , a ) ; cout<<” Order ”<<n<<” : ”<<e n d l ;
f o r ( int j , i =0; i <n ; i ++)
{ f or ( j =0; j <n ; j ++) cout<<a [ i ] [ j ]<< ’ ’ ; cout<<e n d l ; }
}
return 0 ;
}

74
6.22 Optimal Binary Search Tree
int n , a [ maxn ] , s [ maxn ] [ maxn ] , h [ maxn ] [ maxn ] , kk [ maxn ] [ maxn ] ;

int s o l v e ( )
{
int i , j , k , l ; memset ( h , 0 , s i z e o f ( h ) ) ;
fo r ( i =1; i<=n ; i ++) { s [ i ] [ i ]=a [ i ] ; h [ i ] [ i ] = 0 ; kk [ i ] [ i ]= i ;
f o r ( j=i +1; j<=n ; j ++) s [ i ] [ j ]= s [ i ] [ j −1]+a [ j ] ;
}
fo r ( l = 1 ; l <n ; l ++) {
f o r ( i =1; i <n ; i ++) { j=i+l ; h [ i ] [ j ]=0 x 0 f f f f f f f ;
f o r ( k=kk [ i ] [ j − 1 ] ; k<=kk [ i + 1 ] [ j ] ; k++)
i f ( h [ i ] [ k−1]+h [ k + 1 ] [ j ]−a [ k]+ s [ i ] [ j ] < h[ i ][ j ]) {
h [ i ] [ j ] = h [ i ] [ k−1]+h [ k + 1 ] [ j ]+ s [ i ] [ j ]−a [ k ] ;
kk [ i ] [ j ] = k ;
}
}
}
return h [ 1 ] [ n ] ;
}

6.23 Pack Rectangles — Cut Rectangles


struct r e c t { int x1 , y1 , x2 , y2 ; } r [ maxm ] ;
int mk [ maxm ] ;

int i n t e r s e c t ( r e c t a , const r e c t &b , r e c t out [ 4 ] ) // b c u t a


{
i f ( b . x2<=a . x1 | | b . x1>=a . x2 | | b . y2<=a . y1 | | b . y1>=a . y2 ) return 0 ;
i f ( b . x1<=a . x1 && b . x2>=a . x2 && b . y1<=a . y1 && b . y2>=a . y2 ) return −1;
r e c t t ; int nout =0;
i f ( b . x1>a . x1 ) { t=a ; t . x2=b . x1 ; a . x1=b . x1 ; out [ nout++]=t ; }
i f ( b . x2<a . x2 ) { t=a ; t . x1=b . x2 ; a . x2=b . x2 ; out [ nout++]=t ; }
i f ( b . y1>a . y1 ) { t=a ; t . y2=b . y1 ; a . y1=b . y1 ; out [ nout++]=t ; }
i f ( b . y2<a . y2 ) { t=a ; t . y1=b . y2 ; a . y2=b . y2 ; out [ nout++]=t ; }
return nout ;
}

int main ( )
{
r e c t c u r r , t [ 4 ] ; int i , j , k , nn , nr , ans , r r , n ;
c i n >>n ; r r =0;
fo r ( i =0; i <n ; i ++){
c i n >> c u r r . x1 >> c u r r . y1 >> c u r r . x2 >> c u r r . y2 ;
nr=r r ; mk [ r r ] = 1 ; r [ r r++]=c u r r ;
f o r ( j = 0 ; j <nr ; j ++) {
mk [ j ] = 1 ; nn=i n t e r s e c t ( r [ j ] , c u r r , t ) ; i f ( ! nn ) continue ;
i f ( nn < 0 ) mk [ j ] = 0 ; e l s e { r [ j ] = t [−−nn ] ;
while ( nn ) { mk [ r r ] = 1 ; r [ r r ++] = t [−−nn ] ; }
}
}
f o r ( k=j = 0 ; j <r r ; j ++) i f (mk [ j ] ) r [ k++]=r [ j ] ; r r=k ;
}
fo r ( ans=i = 0 ; i <r r ; i ++) ans+=(r [ i ] . x2−r [ i ] . x1 ) ∗ ( r [ i ] . y2−r [ i ] . y1 ) ;
cout<<ans<<e n d l ;
return 0 ;
}

75
6.24 Pack Rectangles — O(N 2 )
int x1 [ maxn ] , y1 [ maxn ] , x2 [ maxn ] , y2 [ maxn ] ;
int y l i s t [ maxn ∗ 2 ] , i d [ maxn ] , n , ny ;

bool cmp( const int&i , const int&j ) { return x1 [ i ]<x1 [ j ] ; }

int GetAreaUnion ( )
{
int i , j , k , rx , l , ans =0;
fo r ( ny=0, i = 0 ; i <n ; i ++) { y l i s t [ ny++]=y1 [ i ] ; y l i s t [ ny++]=y2 [ i ] ; }
s t d : : s o r t ( y l i s t , y l i s t+ny ) ; ny=s t d : : unique ( y l i s t , y l i s t +ny)− y l i s t ;
fo r ( i = 0 ; i <n ; i ++) i d [ i ]= i ; s t d : : s o r t ( id , i d+n , cmp ) ;
fo r ( j = 0 ; j <ny − 1 ; j ++){
rx = −0 x 3 f 3 f 3 f ; l =0;
f o r ( k=0;k<n ; k++){ i = i d [ k ] ;
i f ( y1 [ i ]<= y l i s t [ j ] && y2 [ i ]>= y l i s t [ j +1] && x2 [ i ]> rx ) {
i f ( x1 [ i ]> rx ) l+=x2 [ i ]−x1 [ i ] ; e l s e l+=x2 [ i ]− rx ;
rx = x2 [ i ] ;
}
}
ans += l ∗ ( y l i s t [ j +1]− y l i s t [ j ] ) ;
}
return ans ;
}

6.25 Parliament
Given n > 0, find distinct positive numbers a1 + a2 + ... + ak = n that maximize a1 · a2 · ... · ak .
int main ( )
{
int n , k , p , i , c a s e n o ;
fo r ( c i n >>c a s e n o ; caseno − −; ){ c i n >>n ;
f o r ( p=n , k = 2 ; p>=k ; k++) p−=k ; k−−;
i f ( p<=1){ for ( i =2; i <k ; i ++) cout<<i <<” ” ; cout<<k+p<<e n d l ; } e l s e
i f ( p==k ) { for ( i =3; i<=k ; i ++) cout<<i <<” ” ; cout<<k+2<<e n d l ; } e l s e
{ for ( i =2+(p==k −1); i<=k ; i ++) i f ( i !=k−p +1) cout<<i <<” ” ;
cout<<k+1<<e n d l ; }
i f ( c a s e n o ) cout<<e n d l ;
}
return 0 ;
}

6.26 π Generator
int a =10000 ,b , c =2800 ,d , e , f [ 2 8 0 1 ] , g ;

void GenPI ( ) {
fo r ( ; b−c ; ) f [ b++]=a / 5 ;
fo r ( ; d=0,g=c ∗ 2 ; c −=14, p r i n t f ( ”%.4d” , e+d/ a ) , e=d%a )
f o r ( b=c ; d+=f [ b ] ∗ a , f [ b]=d%−−g , d/=g−−,−−b ; d∗=b ) ;
}

76
6.27 Plant Trees — Iteration
const int maxlen = 5 0 0 0 5 ;
const int maxn = 50000;

int n , s t [ maxlen ] , a [ maxn ] , b [ maxn ] , c [ maxn ] , up ;

int main ( ) {
int i , more ;
while ( c i n >>n ) {
f o r ( i = 0 ; i <n ; i ++){
c i n >>a [ i ]>>b [ i ]>>c [ i ] ;
i f (++b [ i ]>up ) up=b [ i ] ;
}
memset ( s t , 0 , s i z e o f ( s t ) ) ;
f o r ( more = 1 ; more ; ) {
more = 0 ;
f o r ( i = 0 ; i <n ; i ++) i f ( s t [ a [ i ] ] + c [ i ]> s t [ b [ i ] ] )
{ s t [ b [ i ] ] = s t [ a [ i ] ] + c [ i ] ; more = 1 ; }
f o r ( i = 1 ; i<=up ; i ++) {
i f ( s t [ i −1]+1< s t [ i ] ) { s t [ i −1]= s t [ i ] − 1 ; more = 1 ; }
i f ( s t [ i − 1 ] >s t [ i ] ) { s t [ i ]= s t [ i − 1 ] ; more = 1 ; }
}
f o r ( i=up ; i > 0 ; i −−){
i f ( s t [ i ]−1> s t [ i − 1 ] ) { s t [ i −1]= s t [ i ] − 1 ; more = 1 ; }
i f ( s t [ i −1]> s t [ i ] ) { s t [ i ]= s t [ i − 1 ] ; more = 1 ; }
}
}
cout<<s t [ up] < < e n d l ;
}
return 0 ;
}

6.28 Plant Trees — Segment Tree


#define maxn 5 0 0 0 0
#define maxup 5 0 0 0 6

int nspan , span [ maxn ] [ 3 ] , up , t r e e [ maxup ] ;


int iteam [ maxup ] , next [ maxup ] , num ;

int funt comp ( const void ∗ a , const void ∗ b )


{ return ( ( const int ∗ ) b ) [ 0 ] − ( ( const int ∗ ) a ) [ 0 ] ; }

void add ( int r )


{ for ( ; r<=up ; r+=r &( r ˆ ( r −1))) ++ t r e e [ r ] ; }

int sum ( int r )


{ int ans = 0 ; for ( ; r > 0 ; r−=r &( r ˆ ( r − 1 ) ) ) ans+=t r e e [ r ] ; return ans ; }

void go ( )
{
int j , k , i , ans = 0 ; up=0;
fo r ( i = 0 ; i <nspan ; ++ i ) {
s c a n f ( ”%d %d %d” , & span [ i ] [ 0 ] , & span [ i ] [ 1 ] , & span [ i ] [ 2 ] ) ;
++span [ i ] [ 0 ] ; + + span [ i ] [ 1 ] ;
i f ( span [ i ] [ 1 ] > up ) up=span [ i ] [ 1 ] ;
}
q s o r t ( span , nspan , s i z e o f ( int ) ∗ 3 , funt comp ) ;
fo r ( j =0; j<=up ; j ++) next [ j ]= j +1;
next [ up ] = 0 ; memset ( t r e e , 0 , ( up+1)∗ s i z e o f ( int ) ) ;
fo r ( i = 0 ; i <nspan ; i ++){

77
k=sum ( span [ i ] [ 1 ] ) − sum ( span [ i ] [ 0 ] − 1 ) ;
i f ( k>=span [ i ] [ 2 ] ) continue ; e l s e k=span [ i ] [ 2 ] − k ;
j=span [ i ] [ 0 ] ; i f ( next [ j −1]!= j ) j=next [ j ] ;
while ( k−−){
next [ span [ i ] [ 0 ] ] = next [ span [ i ] [ 0 ] − 1 ] = next [ j ] ;
ans ++; add ( j ) ; j=next [ j ] ;
}
}
p r i n t f ( ”%d\n” , ans ) ;
}

int main ( ) {
while( 1== s c a n f ( ”%d” , & nspan ) ) go ( ) ;
return 0 ;
}

6.29 Range Maximum Query


O(N log N ) Preprocess, O(1) Query

int n , L , q , a [ maxn ] , h [ maxn ] [ maxL ] ; // maxL = s q r t {N} + 3

void P r e P r o c e s s ( )
{
int i , j , l ;
fo r ( i =0; i <n ; i ++) h [ i ] [ 0 ] = a [ i ] ;
fo r ( j =1, l = 1 ; l ∗2<=n ; j ++, l ∗=2) for ( i = 0 ; i<=n−l ∗ 2 ; i ++)
h [ i ] [ j ] = ( h [ i ] [ j −1]>h [ i+l ] [ j − 1 ] ) ? h [ i ] [ j − 1 ] : h [ i+l ] [ j − 1 ] ;
}

int Query ( int be , int ed ) // r e t u r n max{a [ op . . ed ] }


{
int j =0, l = 1 ; while ( 2 ∗ l<=ed−be + 1 ) { j ++; l ∗ = 2 ; }
return ( h [ be ] [ j ]>h [ ed+1− l ] [ j ] ) ? h [ be ] [ j ] : h [ ed+1− l ] [ j ] ;
}

O(N ) Preprocess, O( N ) Query

int a [ maxn ] , b [ maxL ] , n , L , q ;

void P r e P r o c e s s ( )
{
int i , j , up , k ; L = ( int ) s q r t ( n ) ;
fo r ( i=k = 0 ; i <n ; k ++ ) {
up=i+L ; i f ( up>n ) up = n ;
f o r ( j=i + 1 ; j <up ; j ++) i f ( a [ j ]>a [ i ] ) i=j ;
b [ k]= i ; i=up ;
}
}

int Query ( int be , int ed ) // r e t u r n max{a [ op . . ed ] }


{
int i , up , u , v , k ;
u = be / L ; v = ed / L ; k = be ;
i f ( u<v ) {
k=be ; up=(u+1)∗L ;
f o r ( i=u + 1 ; i <v ; i ++) i f ( a [ b [ i ]] > a [ k ] ) k = b[ i ];
f o r ( i=be ; i <up ; i ++) i f ( a [ i ]>a [ k ] ) k = i;
f o r ( i=v∗L ; i<=ed ; i ++) i f ( a [ i ]>a [ k ] ) k = i;
} e l s e f o r ( i=be ; i<=ed ; i ++) i f ( a [ i ]>a [ k ] ) k = i;
return k ;
}

78
6.30 Travelling Salesman Problem
int n , x [ maxn ] , y [ maxn ] , i d [ maxn ] ;
double g [ maxn ] [ maxn ] ;

double d i s ( int x1 , int y1 , int x2 , int y2 )


{ return s q r t ( ( x1−x2 ) ∗ ( x1−x2 )+( y1−y2 ) ∗ ( y1−y2 ) ) ; }

double s o l v e ( )
{
int i , j , k , l , l o o p ;
double cur , ans=1e30 ;

fo r ( i =0; i <n ; i ++)


f o r ( j =0; j <n ; j ++)
g [ i ] [ j ]= d i s ( x [ i ] , y [ i ] , x [ j ] , y [ j ] ) ;

fo r ( k=0;k<n ; k++)
{
f o r ( l =0; l <50; l ++)
{
f o r ( i =0; i <n ; i ++) i d [ i ]= i ;
s t d : : swap ( i d [ 0 ] , i d [ k ] ) ;
s t d : : r a n d o m s h u f f l e ( i d +1, i d+n ) ;

l o o p =1;
while ( l o o p ) {
l o o p =0;
for ( i =1; i <n ; i ++) for ( j=i +1; j <n−1; j ++)
i f ( g [ id [ i − 1 ] ] [ id [ i ] ] + g [ id [ j ] ] [ id [ j +1]]
> g [ i d [ i − 1 ] ] [ i d [ j ] ] + g [ i d [ i ] ] [ i d [ j + 1 ] ] + 1 e −8 )
{
l o o p =1;
s t d : : r e v e r s e ( i d+i , i d+j +1);
}
};

f o r ( c u r =0, i = 0 ; i <n − 1 ; i ++)


c u r+=g [ i d [ i ] ] [ i d [ i + 1 ] ] ;

i f ( cur<ans ) ans=c u r ;
}
}
return ans ;
}

79
6.31 Tree Heights
#define maxn 5 0 0 3 ∗ 4

int n , num , nbs [ maxn ] , next [ maxn ∗ 2 ] , h [ maxn ] ;


int out1 [ maxn ] , out2 [ maxn ] , son1 [ maxn ] , i n [ maxn ] , v a l u e [ maxn ] ;
int son [ maxn ] , pnt [ maxn ] , bro [ maxn ] , w e i g h t [ maxn ] , i d [ maxn ] ;

void s o l v e ( )
{
int i , j , k ( 1 ) , l ;
id [ 1 ] = 1 ; weight [1]= in [ 1 ] = 0 ;
fo r ( i =1; i<=k ; i ++) for ( j=son [ i d [ i ] ] ; j ; j=bro [ j ] ) i d [++k]= j ;
fo r ( i =2; i<=n ; i ++) w e i g h t [ i ] = 1 ;
fo r ( k=n ; k >0;k−−){ i=i d [ k ] ;
f o r ( j=son [ i ] ; j ; j=bro [ j ] )
i f ( out1 [ j ]+ w e i g h t [ j ]>=out1 [ i ] )
{ out2 [ i ]= out1 [ i ] ; out1 [ i ]= out1 [ j ]+ w e i g h t [ j ] ; son1 [ i ]= j ; }
e l s e i f ( out1 [ j ]+ w e i g h t [ j ]> out2 [ i ] ) out2 [ i ]= out1 [ j ]+ w e i g h t [ j ] ;
}
fo r ( k=2;k<=n ; k++){ i=i d [ k ] ; i n [ i ] = 0 ;
i f ( i n [ pnt [ i ]] > i n [ i ] ) i n [ i ]= i n [ pnt [ i ] ] ;
i f ( i==son1 [ pnt [ i ] ] ) l=out2 [ pnt [ i ] ] ; e l s e l=out1 [ pnt [ i ] ] ;
i f ( l >i n [ i ] ) i n [ i ]= l ; i n [ i ]+=w e i g h t [ i ] ;
}
}

void d f s ( int node )


{
fo r ( int j , i=nbs [ node ] ; i ; i=next [ i ] ) {
j=v a l u e [ i ] ; i f ( j==pnt [ node ] ) continue ;
pnt [ j ]= node ; bro [ j ]= son [ node ] ; son [ node ]= j ; d f s ( j ) ;
}
}

void out ( )
{
int maxh=−1, minh=n+1, i ;
fo r ( i =1; i<=n ; i ++) {
i f ( i n [ i ]< out1 [ i ] ) h [ i ]= out1 [ i ] ; e l s e h [ i ]= i n [ i ] ;
i f ( h [ i ]>maxh ) maxh=h [ i ] ; i f ( h [ i ]<minh ) minh=h [ i ] ;
}
cout<<” Best Roots : ” ;
fo r ( i =1; i<=n ; i ++) i f ( h [ i ]==minh ) cout<<” ”<<i ;
cout<<e n d l <<”Worst Roots : ” ;
fo r ( i =1; i<=n ; i ++) i f ( h [ i ]==maxh ) cout<<” ”<<i ;
cout<<e n d l ;
}

int main ( )
{
int i , j , k , l ;
while ( c i n >>n ) {
f o r ( i =1; i<=n ; i ++)
out1 [ i ]= out2 [ i ]= son1 [ i ]= son [ i ]= bro [ i ]= pnt [ i ]= next [ i ]= nbs [ i ] = 0 ;
f o r (num=1, i =1; i<=n ; i ++){ c i n >>l ; f o r ( k=0;k<l ; k++)
{ c i n >>j ; v a l u e [ num]= j ; next [ num]= nbs [ i ] ; nbs [ i ]=num++;} }
d f s ( 1 ) ; s o l v e ( ) ; out ( ) ;
}
return 0 ;
}

80
6.32 Minimum Cyclic Presentation
int MinimumCyclicPresentation ( char ∗ s , int n )
{
int i , j , x , y , u , v ;
fo r ( x=0,y = 1 ; y<n ; y++) i f ( s [ y]<=s [ x ] )
{
i=u=x ; j=v=y ;
while ( s [ i ]==s [ j ] )
{
++u ; i f ( ++ i == n ) i =0;
++v ; i f ( ++ j == n ) j =0;
i f ( i==x ) break ;
}
i f ( s [ i ]<=s [ j ] ) y = v ; e l s e
{ x = y ; i f ( u>y ) y = u ; }
}
return x ;
}

81
6.33 Maximum Clique
int l i s t [ maxn ] [ maxn ] , g [ maxn ] [ maxn ] , s [ maxn ] , d e g r e e [ maxn ] , b e h i d e [ maxn ] ;
int found , n , curmax , c u r o b j ;

void s o r t d e g r e e ( )
{
fo r ( int j , k , l , i =1; i<=n ; i ++) {
f o r ( k=i , j=i +1; j<=n ; j ++) i f ( d e g r e e [ j ]< d e g r e e [ k ] ) k=j ;
i f ( k!= i ) {
s t d : : swap ( d e g r e e [ i ] , d e g r e e [ k ] ) ;
f o r ( l =1; l<=n ; l ++) s t d : : swap ( g [ i ] [ l ] , g [ k ] [ l ] ) ;
f o r ( l =1; l<=n ; l ++) s t d : : swap ( g [ l ] [ i ] , g [ l ] [ k ] ) ;
}
}
}

void d f s ( int d )
{
i f ( d−1>curmax ) { found =1; return ; } ;
int i , j ;
fo r ( i =1; i < l i s t [ d −1][0] − curmax+d ; i ++)
i f ( ! found && d+b e h i d e [ l i s t [ d − 1 ] [ i ]+1] > curmax &&
( l i s t [ d−1][0]== i | | d+b e h i d e [ l i s t [ d − 1 ] [ i +1]] > curmax ) ) {
f o r ( j=i +1, l i s t [ d ] [ 0 ] = 0 ; j<=l i s t [ d − 1 ] [ 0 ] ; j ++)
i f ( g [ l i s t [ d−1][ j ] ] [ l i s t [ d−1][ i ] ] )
l i s t [ d][++ l i s t [ d ] [ 0 ] ] = l i s t [ d − 1 ] [ j ] ;
i f ( l i s t [ d ] [ 0 ] = = 0 | | d + b e h i d e [ l i s t [ d ] [ 1 ] ] > curmax ) d f s ( d +1);
}
}

void s o l v e ( )
{
s o r t d e g r e e ( ) ; b e h i d e [ n +1]=0; b e h i d e [ n ] = 1 ;
fo r ( int j , i=n−1; i >0; i −−) {
curmax=b e h i d e [ i + 1 ] ; found= l i s t [ 1 ] [ 0 ] = 0 ;
f o r ( j=i +1; j<=n ; j ++) i f ( g [ j ] [ i ] ) l i s t [ 1 ] [ + + l i s t [ 1 ] [ 0 ] ] = j ;
d f s ( 2 ) ; b e h i d e [ i ]=curmax+found ;
} cout<<b e h i d e [1]<< e n d l ;
}

int main ( )
{
int i , j ;
while ( c i n >>n , n ) {
f o r ( i =1; i<=n ; i ++) for ( j =1, d e g r e e [ i ] = 0 ; j<=n ; j ++) {
c i n >> g [ i ] [ j ] ;
d e g r e e [ i ]+=(g [ i ] [ j ] ! = 0 ) ;
} solve ( ) ;
}
return 0 ;
}

82
6.34 Maximal Non-Forbidden Submatrix
#define f o r b i d d e n 1

int wx , wy , g [ maxn ] [ maxn ] , h [ maxn ] , r [ maxn ] , l [ maxn ] ;

int s o l v e ( )
{
int i , j , k , ans , l e f t , r i g h t ;
ans = 0 ; memset ( h , 0 , s i z e o f ( h ) ) ;
fo r ( i =0; i <wx ; i ++) {
f o r ( j =0; j <wy ; j ++) i f ( g [ i ] [ j ] ! = f o r b i d d e n ) h [ j ]++; e l s e h [ j ] = 0 ;
f o r ( j =0; j <wy ; j ++) i f ( h [ j ] ) {
i f ( j = = 0 | | h [ j −1]==0) l e f t =j ;
i f ( i = = 0 | | g [ i − 1 ] [ j ]== f o r b i d d e n ) l [ j ]= l e f t ;
i f ( l e f t >l [ j ] ) l [ j ]= l e f t ;
}
f o r ( j=wy−1; j >=0; j −−) i f ( h [ j ] ) {
i f ( j==wy − 1 | | h [ j +1]==0 ) r i g h t=j ;
i f ( i = = 0 | | g [ i − 1 ] [ j ]== f o r b i d d e n ) r [ j ]= r i g h t ;
i f ( r i g h t <r [ j ] ) r [ j ]= r i g h t ;
}
f o r ( j =0; j <wy ; j ++)
i f ( ( r [ j ]− l [ j ]+1)∗ h [ j ] > ans ) ans = ( r [ j ]− l [ j ]+1)∗ h [ j ] ;
}
return ans ;
}

6.35 Maximum Two Chain Problem


typedef struct { int x , y ; } p o i n t ;

int cmp( const void ∗ e1 , const void ∗ e2 ) {


const p o i n t ∗ p1 = ( const p o i n t ∗ ) e1 ;
const p o i n t ∗ p2 = ( const p o i n t ∗ ) e2 ;
i f ( p1−>x ! = p2−>x ) return p1−>x − p2−>x ;
return p1−>y − p2−>y ;
}

int n ;
p o i n t p [MAX] ;

void i n i t i a l i z e ( ) {
int i ;
for ( s c a n f ( ”%d” , & n ) , i = 1 ; i <= n ; i ++)
s c a n f ( ”%d%d” , & p [ i ] . x , & p [ i ] . y ) ;

q s o r t (&p [ 1 ] , n , s i z e o f ( p o i n t ) , cmp ) ;
p [ 0 ] . x = p [ 0 ] . y = 0;
}

int deg [MAX] = { 0 } , queue [MAX] ;


int maxlevel , l e v e l [MAX] = { 0 } ;
int l e f t [MAX] = { 0 } , r i g h t [MAX] = { 0 } , mark [MAX] = { 0 } ;

83
void l o c a l c h a i n () {
int i , j ;
for ( i = 1 ; i <= n ; i ++)
for ( j = i + 1 ; j <= n ; j ++)
if (p[ i ] . y <= p [ j ] . y )
deg [ i ]++;

for ( queue [ 0 ] = 0 , i = 1 ; i <= n ; i ++)


i f ( deg [ i ] = = 0 )
queue[++queue [ 0 ] ] = i ;
for ( i = 1 , m a x l e v e l = −1; i <= queue [ 0 ] ; i ++)
f o r ( j = 1 ; j < queue [ i ] ; j ++)
i f ( p [ j ] . y <= p [ queue [ i ] ] . y )
i f (−−deg [ j ] = = 0 ) {
queue[++queue [ 0 ] ] = j , l e v e l [ j ] = l e v e l [ queue [ i ] ] + 1 ;
i f ( l e v e l [ j ] > maxlevel ) maxlevel = l e v e l [ j ] ;
}
fo r ( m a x l e v e l ++, i = 1 ; i <= n ; i ++)
l e v e l [ i ] = maxlevel − l e v e l [ i ] ;

for ( mark [ 0 ] = n + 1 , i = 1 ; i <= n ; i ++) {


f o r ( j = 0 ; j < i ; j ++)
i f ( mark [ j ] && l e v e l [ j ] == l e v e l [ i ] − 1 && p [ j ] . y <= p [ i ] . y )
break ;
if ( j < i ) {
i f ( l e f t [ l e v e l [ i ] ] = = 0 ) l e f t [ l e v e l [ i ] ] = i , mark [ i ] = n + 1 ;
mark [ r i g h t [ l e v e l [ i ] ] ] − − ;
mark [ r i g h t [ l e v e l [ i ] ] = i ]++;
}
}
}

int i n d e x [MAX] , v a l u e [MAX] = { 0 } , l e v v a l u e [MAX] ;

int index cmp ( const void ∗ e1 , const void ∗ e2 ) {


return l e v e l [ ∗ ( const int ∗ ) e1 ] − l e v e l [ ∗ ( const int ∗ ) e2 ] ;
}

void c a l c v a l u e ( ) {
int q , i , j , l e v ;
fo r ( i = 1 ; i <= n ; i ++)
index [ i ] = i ;
q s o r t ( index , n , s i z e o f ( int ) , index cmp ) ;

for ( q = 1 ; q <= n ; q++) {


le v = l e v e l [ i = index [ q ] ] ;

i f ( l e f t [ l e v ] == i && r i g h t [ l e v ] == i )
value [ i ] = levvalue [ lev − 1] + 1;
e l s e i f ( l e f t [ l e v ] == i | | r i g h t [ l e v ] == i )
value [ i ] = levvalue [ lev − 1] + 2;
else
f o r ( j = 0 ; j < i ; j ++) {
i f ( mark [ j ] ) v a l u e [ j ] = l e v v a l u e [ l e v e l [ j ] ] ;
i f ( p [ j ] . y <= p [ i ] . y && v a l u e [ j ] + l e v e l [ i ] − l e v e l [ j ] + 1 > v a l u e [ i ] )
value [ i ] = value [ j ] + l e v e l [ i ] − l e v e l [ j ] + 1 ;
}

i f ( value [ i ] > levvalue [ lev ] )


levvalue [ lev ] = value [ i ] ;
}
}

84
void p u t a n s w e r ( ) {
int i , max = 0 ;
for ( i = 1 ; i <= n ; i ++)
i f ( v a l u e [ i ] > max)
max = v a l u e [ i ] ;
p r i n t f ( ”%d\n” , max ) ;
}

void main ( ) {
initialize ();
local chain ();
calc value ();
put answer ( ) ;
}

6.36 N Queens Problem


int main ( ) {
int n , i , odd ;
while ( c i n >>n ) {
i f ( n <4) cout<<” I m p o s s i b l e ” ; e l s e
i f ( ( n/2)%3!=1){
cout <<2;
f o r ( i = 4 ; i<=n ; i +=2) cout<<” ”<<i ;
f o r ( i = 1 ; i<=n ; i +=2) cout<<” ”<<i ;
} else {
i f ( n & 1 ) { n−−; odd = 1 ; } e l s e odd =0;
cout << n / 2 ;
f o r ( i=n / 2 + 1 ; i !=n /2 −1; i =( i +2)%n ) cout<<” ”<<i +1;
f o r ( i =( i+n−2)%n ; i !=n /2 −1; i =( i+n−2)%n ) cout<<” ”<<n−i ;
cout<<” ”<<n−i ; i f ( odd ) cout<<” ”<<n+1;
}
cout<<e n d l ;
}
return 0 ;
}

6.37 de Bruijn Sequence Generator


int go[1<<maxn ] , s t a r t , now , n , k , a[(1<<maxn)+maxn ] , i , ans , c a s e n o ;

int main ( )
{
ifstream cin ( ” input . txt ” ) ;
fo r ( c i n >>c a s e n o ; caseno − −;){ c i n >>n>>k ;
memset ( go , 0 , s i z e o f ( go ) ) ; memset ( a , 0 , s i z e o f ( a ) ) ;
now=s t a r t =(1<<(n −1)) −1; i =0;
do { i f ( go [ now ] ) { a [ i ++]=1; now=(now∗2+1)& s t a r t ; }
e l s e { go [ now ] = 1 ; a [ i ++]=0; now=(now∗2)& s t a r t ; }
} while ( now!= s t a r t ) ;
a [ i ++]=1;
f o r ( i = 0 ; i <n ; i ++) a [ i +(1<<n )]= a [ i ] ;
f o r ( ans=i = 0 ; i <n ; i ++) ans=ans∗2+a [ k+i ] ;
cout<<ans<<e n d l ;
}
return 0 ;
}

85
6.38 ZOJ 1482 Partition
#define maxn 3 0 1 0

int n , pnt [ maxn ] , rank [ maxn ] ;

int f i n d ( int x )
{
i f ( x!= pnt [ x ] ) pnt [ x]= f i n d ( pnt [ x ] ) ;
return pnt [ x ] ;
}

int main ( ) {
int i , j , ans ( 0 ) , x ;
c i n >> n ;
memset ( pnt , 0 , s i z e o f ( pnt ) ) ;
fo r ( i = 1 ; i<=n ; i ++) for ( j = 1 ; j<=n ; j ++){
c i n >>x ;
i f ( ! x ){
i f ( pnt [ j ] ) pnt [ f i n d ( j )]= j ;
i f ( pnt [ j −1]) pnt [ j −1]= j ;
pnt [ j ]= j ;
} e l s e { i f ( pnt [ j ]== j ) ans ++; pnt [ j ] = 0 ; }
}
fo r ( i = 1 ; i<=n ; i ++) i f ( pnt [ i ]== i ) ans++;
cout<<ans<<e n d l ;
return 0 ;
}

86

You might also like