acm 算法模板 适合初学者使用【转】

三角形面积计算 ……………………………………………………………………………………. 1
字典树模板 ………………………………………………………………………………………….. 2
求线段所在直线 ……………………………………………………………………………………. 3
求外接圆……………………………………………………………………………………………… 4
求内接圆……………………………………………………………………………………………… 5
判断点是否在直线上 ……………………………………………………………………………… 6
简单多边形面积计算公式 ……………………………………………………………………….. 7
stein算法求最大共约数 ………………………………………………………………………….. 8
最长递增子序列模板——o(nlogn算法实现)……………………………………………….. 9
判断图中同一直线的点的最大数量 ………………………………………………………….10
公因数和公倍数 ………………………………………………………………………………….. 11
已知先序中序求后序 ……………………………………………………………………………. 12
深度优先搜索模板……………………………………………………………………………….. 13
匈牙利算法——二部图匹配BFS实现……………………………………………………… 14
带输出路径的prime算法………………………………………………………………………. 15
prime模板………………………………………………………………………………………….. 16
kruskal模板 ………………………………………………………………………………………..17
dijsktra ………………………………………………………………………………………………. 18
并查集模板 ………………………………………………………………………………………… 19
高精度模板 ………………………………………………………………………………………… 20

三角形面积计算

//已知三条边和外接圆半径,公式为s = a*b*c/(4*R)

double GetArea(double a, double b, double c, double R)
{
    return a*b*c/4/R;
}

//已知三条边和内接圆半径,公式为s = pr

double GetArea(double a, double b, double c, double r)
 {  
     return r*(a+b+c)/2;
 }  

//已知三角形三条边,求面积

double GetArea(doule a, double b, double c) 
{  
    double p = (a+b+c)/2;  
    return sqrt(p*(p-a)*(p-b)*(p-c)); 
}

//已知道三角形三个顶点的坐标

struct Point 
{  
    double x, y;  
    Point(double a = 0, double b = 0) 
    {     
        x = a; 
        y = b; 
    } 
};  
double GetArea(Point p1, Point p2, Point p3) 
{  
    double t =  -p2.x*p1.y+p3.x*p1.y+p1.x*p2.y-p3.x*p2.y-p1.x*p3.y+p2.x*p3.y; 
    if(t < 0) t = -t; 
    return t/2; 
}

字典树模板

#include <stdio.h> 
#include <string.h> 
#include <memory.h> 
#define BASE_LETTER 'a' 
#define MAX_TREE 35000 
#define MAX_BRANCH 26 

struct {      
    int next[MAX_BRANCH]; //记录分支的位置     
    int c[MAX_BRANCH]; //查看分支的个数      
    int flag; //是否存在以该结点为终止结点的东东,可以更改为任意的属性  
}trie[MAX_TREE]; 

int now;  

void init() 
{  
    now = 0;  
    memset(&trie[now], 0, sizeof(trie[now]));
    now++;
}

int add () 
{      
    memset(&trie[now], 0, sizeof(trie[now]));     
    return now++; 
}  

int insert( char *str) 
{
    int pre = 0, addr;
    while( *str != 0 )     
    {      
        addr = *str - BASE_LETTER;
        if( !trie[pre].next[addr] )
            trie[pre].next[addr] = add(); 
        trie[pre].c[addr]++;          
        pre = trie[pre].next[addr];
        str++;
    }
    trie[pre].flag = 1;       
    return pre; 
}

int search( char *str ) 
{       
    int pre = 0, addr;     
    while( *str != 0 )     
    {         
        addr = *str - BASE_LETTER;         
        if ( !trie[pre].next[addr] )             
            return 0;          
        pre = trie[pre].next[addr];         
        str ++;     
    }      
    if( !trie[pre].flag )         
        return 0;
    return pre;
} 

pku2001题,源代码:

void check( char *str ) 
{  
    int pre = 0, addr; 
    while(*str != 0) 
    {     
        addr = *str - BASE_LETTER;          
        if( trie[pre].c[addr] == 1)    
        {  
            printf("%c\n", *str);     
            return;    
        }        
        printf("%c", *str);          
        str ++; 
    }  
    printf("\n"); 
}  

char input[1001][25];  
int main() 
{  
    int i = 0,j; 
    init();  
    while(scanf("%s", input[i]) != EOF) 
    {     
        getchar();     
        insert(input[i]);    
        i++; 
    }  
    for(j = 0; j < i; j ++) 
    {     
        printf("%s ", input[j]);    
        check(input[j]); 
    }  
    return 0;
}

求线段所在直线

struct Line 
{  
    double a, b, c; 
}; 

struct Point 
{  
    double x, y; 
}  
Line GetLine(Point p1, Point p2) 
{  
    //ax+by+c = 0返回直线的参数 
    Line line;  
    line.a = p2.y - p1.y; 
    line.b = p1.x - p2.x;  
    line.c = p2.x*p1.y - p1.x*p2.y; 
    return line;
}

求外接圆

//已知三角形三个顶点坐标,求外接圆的半径和坐标

struct Point 
{  
    double x, y;  
    Point(double a = 0, double b = 0) 
    {  
        x = a; 
        y = b; 
    } 
};  

struct TCircle 
{  
    double r; 
    Point p; 
}  

double distance(Point p1, Point p2) 
{  
    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); 
}

double GetArea(doule a, double b, double c) 
{  
    double p = (a+b+c)/2;  
    return sqrt(p*(p-a)*(p-b)*(p-c)); 
}  

TCircle GetTCircle(Point p1, Point p2, Point p3) 
{  
    double a, b, c;  
    double xa, ya, xb, yb, xc, yc, c1, c2; 
    TCircle tc;   
    a = distance(p1, p2); 
    b = distance(p2, p3); 
    c = distance(p3, p1);

    //求半径  
    tc.r = a*b*c/4/GetArea(a, b, c); 

    //求坐标  
    xa = p1.x; ya = p1.b; 
    xb = p2.x; yb = p2.b; 
    xc = p3.x; yc = p3.b;  

    c1 = (xa*xa + ya*ya - xb*xb - yb*yb)/2; 
    c2 = (xa*xa + ya*ya - xc*xc - yc*yc)/2; 

    tc.p.x = (c1*(ya-yc) - c2*(ya-yb))/((xa-xb)*(ya-yc) - (xa-xc)*(ya-yb)); 
    tc.p.y = (c1*(xa-xc) - c2*(xa-xb))/((ya-yb)*(xa-xc) - (ya-yc)*(xa-xb)); 
    return tc; 
}

求内接圆

struct Point 
{  
    double x, y;  
    Point(double a = 0, double b = 0) 
    {     
        x = a; y = b; 
    } 
};  

struct TCircle 
{
    double r; 
    Point p; 
}  

double distance(Point p1, Point p2) 
{  
    return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); 
}  

double GetArea(doule a, double b, double c) 
{  
    double p = (a+b+c)/2;  
    return sqrt(p*(p-a)*(p-b)*(p-c)); 
}  

TCircle GetTCircle(Point p1, Point p2, Point p3)
{  
    double a, b, c;  
    double xa, ya, xb, yb, xc, yc, c1, c2, f1, f2; 
    double A,B,C; 
    TCircle tc;  

    a = distance(p1, p2); 
    b = distance(p3, p2); 
    c = distance(p3, p1);  

   //求半径  
   tc.r = 2*GetArea(a, b, c)/(a+b+c);

    //求坐标  
    A = acos((b*b+c*c-a*a)/(2*b*c)); 
    B = acos((a*a+c*c-b*b)/(2*a*c)); 
    C = acos((a*a+b*b-c*c)/(2*a*b)); 

    p = sin(A/2); p2 = sin(B/2); p3 = sin(C/2); 

    xb = p1.x; yb = p1.b; 
    xc = p2.x; yc = p2.b; 
    xa = p3.x; ya = p3.b; 

    f1 = ( (tc.r/p2)*(tc.r/p2) - (tc.r/p)*(tc.r/p) + xa*xa - xb*xb + ya*ya - yb*yb)/2;  

    tc.p.x = (f1*(ya-yc) - f2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb)); 
    tc.p.y = (f1*(xa-xc) - f2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb)); 

    return tc;
}

判断点是否在直线上

//判断点p是否在直线[p1,p2]

struct Point 
{  
    double x,y; 
};  
bool isPointOnSegment(Point p1, Point p2, Point p0) 
{  
    //叉积是否为0,判断是否在同一直线上  
    if((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y) != 0)    
        return false;  

    //判断是否在线段上  
    if((p0.x > p1.x && p0.x > p2.x) || (p0.x < p1.x && p0.x < p2.x))    
        return false;  

    if((p0.y > p1.y && p0.y > p1.y) || (p0.y < p1.y && p0.y < p2.y))    
        return false; 

    return true; 
}

简单多边形面积计算公式

struct Point 
{  
    double x, y;  
    Point(double a = 0, double b = 0) 
    {     
        x = a; y = b; 
    } 
}; 

Point pp[10];  

double GetArea(Point *pp, int n)  
{
    //n为点的个数,pp中记录的是点的坐标 
    int i = 1; 
    double t = 0; 
    for(; i <= n-1; i++)     
    t += pp[i-1].x*pp[i].y - pp[i].x*pp[i-1].y; 
    t += pp[n-1].x*pp[0].y - pp[0].x*pp[n-1].y; 
    if(t < 0) t = -t; 
    return t/2; 
} 

stein算法求最大共约数

int gcd(int a,int b) 
{  
    if (a == 0) return b; 
    if (b == 0) return a;  
    if (a % 2 == 0 && b % 2 == 0) return 2 * gcd(a/2,b/2); 
    else if (a % 2 == 0) return gcd(a/2,b); 
    else if (b % 2 == 0) return gcd(a,b/2); 
    else return gcd(abs(a-b),min(a,b)); 
} 

最长递增子序列模板——o(nlogn算法实现)

#include <stdio.h> 
#define MAX 40000

int array[MAX], B[MAX];  

int main() 
{  
    int count,i,n,left,mid,right,Blen=0,num;  
    scanf("%d",&count); //case的个数  
    while(count--) 
    {     
        scanf("%d",&n); //每组成员的数量 Blen = 0;   
        for(i=1;i<=n;i++)      
            scanf("%d",&array[i]); //读入每个成员
        for(i=1;i<=n;i++)    
        {              
            num = array[i];             
            left = 1;
            right = Blen;            
            while(left<=right)             
            {                  
                mid = (left+right)/2;                 
                if(B[mid]<num)                     
                    left = mid+1;                 
                else                      
                    right = mid-1;             
            }              
            if(Blen<left)                 
                Blen++;    
        }     
        printf("%d\n",Blen);//输出结果 
    }
    return 1;
}

判断图中同一直线的点的最大数量

#include <iostream> 
#include <cstdio> 
#include <memory> 
using namespace std;  
#define MAX 1010 //最大点的个数 

struct point 
{  
    int x,y; 
}num[MAX];  
int used[MAX][MAX*2]; //条件中点的左边不会大于1000,just equal MAX 
int countN[MAX][MAX*2]; 

#define abs(a) (a>0?a:(-a)) 
int GCD(int x, int y) 
{  
    int temp; 
    if(x < y) 
    {     
        temp = x; 
        x = y; 
    }  
    while(y != 0)
    {
        temp = y;    
        y = x % y;    
        x = temp; 
    }  
    return x; 
}

int main() 
{  
    int n,i,j;  
    int a,b,d,ans;  
    while(scanf("%d", &n)==1) 
    {
       //inite    
        ans = 1;     
        memset(used, 0, sizeof(used));     
       memset(countN, 0, sizeof(countN));        
       //read     
        for(i = 0; i < n; i++)      
        scanf("%d%d", &num[i].x, &num[i].y);     
        for(i = 0; i < n-1; i++)    
        {      
            for(j = i+1; j < n; j++)     
            {       
                b = num[j].y-num[i].y;      
                a = num[j].x-num[i].x;       
                if(a < 0) //这样可以让(2,3)(-2,-3)等价
                {
                    a = -a; b = -b;
                }      
                d = GCD(a,abs(b));      
                a /= d;        
                b /= d; 
                b += 1000;//条件中点的左边不会大于1000  
                if(used[a][b] != i+1)      
                {        
                    used[a][b] = i+1;       
                    countN[a][b] = 1;      
                }      
                else      
                {        
                    countN[a][b]++;        
                    if(ans < countN[a][b])        
                        ans = countN[a][b];
                }      
            }//for    
        }//for     
       printf("%d\n", ans+1); 
    }  
    return 0; 
}

公因数和公倍数

int GCD(int x, int y) 
{  
    int temp; 
    if(x < y) 
    {     
        temp = x; x = y; y = temp; 
    }  
    while(y != 0) 
    {     
        temp = y;    
        y = x % y;    
        x = temp; 
    }  
    return x; 
}

int beishu(int x, int y) 
{  
    return x * y / GCD(x,y); 
} 

已知先序中序求后序

#include <iostream> 
#include <string> 
using namespace std;  

string post;  
void fun(string pre, string mid) 
{  
    if(pre == "" || mid == "") 
        return; 
    int i = mid.find(pre[0]);  
    fun(pre.substr(1,i), mid.substr(0,i));
    fun(pre.substr(i+1, (int)pre.length()-i-1),mid.substr(i+1, (int)mid.length()-i-1)); 
    post += pre[0]; 
}  

int main() 
{  
    string pre, mid; 
    while(cin >> pre) 
    {     
        cin >> mid;    
        post.erase();    
        fun(pre, mid);     
        cout << post << endl; 
    }
    return 0;
}

深度优先搜索模板

int t; //t用来标识要搜索的元素  
int count; //count用来标识搜索元素的个数 
int data[m][n]; //data用来存储数据的数组 

//注意,数组默认是按照1„„n存储,即没有第0行 

//下面是4个方向的搜索, 
void search(int x, int y) 
{  
    data[x][y] = *; 
    //搜索过进行标记 
    if(x-1 >= 1 && data[x-1][y] == t) 
    {     
        count++;     
        search(x-1,y);   
    }
    if(x+1 <= n && data[x+1][y] == t) 
    {     
        count++;     
        search(x+1,y); 
    }  
    if(y-1 >= 1 && data[x][y-1] == t) 
    {     
        count++;     
        search(x,y-1); 
    }  
    if(y+1 <= n && data[x][y+1] == t) 
    {     
        count++;     
        search(x,y+1); 
    } 
}

//下面是8个方向的搜索 
void search(int x, int y) 
{  
    data[x][y] = *; 
    //搜索过进行标记 
    if(x-1 >= 1) 
    {     
        if(data[x-1][y] == t)    
        {      
            count++;      
            search(x-1,y);    
        }     
        if(y-1 >= 1 && data[x-1][y-1] == t)    
        {      
            count++;      
            search(x-1,y-1);
        }     
        if(y+1 <= n && data[x-1][y+1] == t)    
        {      
            count++;      
            search(x-1,y+1);    
        } 
    }  
    if(x+1 <= n) 
    {     
        if(data[x+1][y] == t)    
        {      
            count++;      
            search(x+1,y);    
        }     
        if(y-1 >= 1 && data[x+1][y-1] == t)
        {      
            count++;      
            search(x+1,y-1);    
        }     
        if(y+1 <= n && data[x+1][y+1] == t)    
        { 
            count++;      
            search(x+1,y+1);    
        } 
    }  
    if(y-1 >= 1 && data[x][y-1] == t) 
    {     
        count++;     
        search(x,y-1); 
    }  
    if(y+1 <= n && data[x][y+1] == t) 
    {     
        count++;     
        search(x,y+1); 
    } 
}

匈牙利算法——二部图匹配BFS实现

//匈牙利算法实现  
#define MAX 310          //二部图一侧顶点的最大个数  
int n,m;                 //二分图的两个集合分别含有n和m个元素。 bool map[MAX][MAX];      //map存储邻接矩阵。   

int Bipartite()  
{       
    int i, j, x, ans;    //n为最大匹配数      
    int q[MAX], prev[MAX], qs, qe;       
        //q是BFS用的队列,prev是用来记录交错链的,同时也用来记录右边的点是否被找过      
    int vm1[MAX], vm2[MAX];       
        //vm1,vm2分别表示两边的点与另一边的哪个点相匹配      
    ans = 0;
    memset(vm1, -1, sizeof(vm1));       
    memset(vm2, -1, sizeof(vm2)); 
        //初始化所有点为未被匹配的状态     
    for( i = 0; i < n; i++ )  
    {           
        if(vm1[i] != -1)continue; 
            //对于左边每一个未被匹配的点进行一次BFS找交错链
        for( j = 0; j < m; j++ ) prev[j] = -2; 
            //每次BFS时初始化右边的点                     
        qs = qe = 0; //初始化BFS的队列          

        //下面这部分代码从初始的那个点开始,先把它能找的的右边的点放入队列          
        for( j = 0; j < m; j++ )    
        {      
            if( map[i][j] )      
            {        
                prev[j] = -1;       
                q[qe++] = j;      
            }     
        }
        while( qs < qe )     
        { 

        //BFS              
        x = q[qs];               
        if( vm2[x] == -1 ) break;               
            //如果找到一个未被匹配的点,则结束,找到了一条交错链
        qs++;               

        //下面这部分是扩展结点的代码             
        for( j = 0; j < m; j++ )      
        {       
            if( prev[j] == -2 && map[vm2[x]][j] )      
            {         
                //如果该右边点是一个已经被匹配的点,则vm2[x]是与该点相匹配的左边点         
                //从该左边点出发,寻找其他可以找到的右边点        
                prev[j] = x;        
                q[qe++] = j;       
            }      
        }
    }           
    if( qs == qe ) continue; //没有找到交错链 

    //更改交错链上匹配状态          
    while( prev[x] > -1 )    
    {               
        vm1[vm2[prev[x]]] = x;              
        vm2[x] = vm2[prev[x]];              
        x = prev[x]; 
    }           
    vm2[x] = i;          
    vm1[i] = x;                    
    //匹配的边数加一          
    ans++;      
    }       
    return ans;  
}

带输出路径的prime算法

#include <iostream> 
#include <memory> 
using namespace std;

const int MAX = 110; 
int data[MAX][MAX]; 
int lowcost[MAX]; 
int adjvex[MAX]; 

int main() 
{  
    int n; 
    cin >> n; 
    int i,j;  

    for(i = 0 i < n; i++)    
        for(j = 0; j < n; j++)     
            cin >> data[i][j]; 

    //prim  
    for(i = 1; i < n; i++) 
    {     
        lowcost[i] = data[0][i];    
        adjvex[i] = 0; 
    }  
    for(i = 1; i < n; i++) 
    {     
        int min = 1<<25, choose;    
        for(j = 1; j < n; j++)    
        {      
            if(lowcost[j] && lowcost[j] < min)     
            {
                min = lowcost[j];      
                choose = j;     
            }    
        }     
        printf("<%d %d> %d\n",adjvex[choose]+1,choose+1, lowcost[choose]);    
        lowcost[j] = 0;     
        for(j = 1; j < n; j++)    
        {      
            if(lowcost[j] && lowcost[j] > data[choose][j])     
            {       
                lowcost[j] = data[choose][j];    
                adjvex[j] = choose;     
            }    
        }
    }
    return0;
}

prime模板

#include <iostream> 
#include <memory> 
#include <cmath>  
using namespace std;

int const MAX = 110; 
int dis[MAX][MAX]; 
int lowcost[MAX];

int main() 
{  
    int n; 
    int i,j;  
    while(cin >> n) 
    {  
        for(i = 0; i < n; i++)    
            for(j = 0; j < n; j++)     
                cin >> dis[i][j]; 

        //下面是prim算法部分,ans是计算所有路径的和 
        lowcost[0] = 0;
        for(i = 1; i < n; i++)     
            lowcost[i] = dis[0][i];  
        int ans = 0;  
        for(i = 1; i < n; i++) 
        {     
            double min = (1<<30);    
            int choose;     
            for(j = 1; j < n; j++)    
            {      
                if(lowcost[j] != 0 && lowcost[j] < min)
                {       
                    min = lowcost[j];      
                    choose = j;     
                }    
            }
            ans += lowcost[choose];    
            lowcost[choose] = 0;    
            for(j = 1; j < n; j++)    
            {      
                if(lowcost[j] != 0 && lowcost[j]>dis[choose][j])      
                    lowcost[j] = dis[choose][j];    
            } 
        }  
        cout << ans << endl; 
        }  
    return 0; 
} 

kruskal模板

#include <iostream> 
#include <memory> 
#include <algorithm> 
using namespace std;  

const int MAX = 1010; //节点个数 
const int MAXEDGE = 15010; //边个数 
bool used[MAXEDGE]; //标记边是否用过 

struct node 
{
    int begin, end, dis; 
}data[MAXEDGE];  

class UFSet 
{  
private:  
    int parent[MAX+1]; 
public:  
    UFSet(int s = MAX); 
    int Find(int x);  
};  

UFSet::UFSet(int s) 
{  
    size = s+1;  
    memset(parent, -1, sizeof(int)*size); 
} 

void UFSet::Union(int root1, int root2) 
{  
    int temp = parent[root1] + parent[root2]; 
    if(parent[root1] <= parent[root2]) 
    {     
        parent[root2] = root1;     
        parent[root1] = temp; 
    } 
    else 
    {     
        parent[root1] = root2;    
        parent[root2] = temp; 
    } 
}  

int UFSet::Find(int x) 
{  
    int p = x;  
    while(parent[p] > 0)    
        p = parent[p]; 
    int t = x; 
    while(t != p) 
    {     
        t = parent[x];    
        parent[x] = p;    
        x = t;
    }  
    return p; 
}  

bool cmp(node a, node b) 
{  
    return (a.dis < b.dis); 
}  

int main() 
{  
    int n, m;  
    scanf("%d%d", &n, &m); 
    int i,j;  
    for(i = 0; i < m; i++)     
        scanf("%d%d%d", &data[i].begin, &data[i].end, &data[i].dis);

    //最小生成树 
    UFSet ufs(n);  
    sort(data, data+m, cmp);

    int root1, root2; 
    int total = 0;  
    for(i = 0; i < m; i++) 
    {     
        root1 = ufs.Find(data[i].begin);    
        root2 = ufs.Find(data[i].end);    
        if(root1 == root2) continue;    
        ufs.Union(root1, root2);    
        used[i] = true;    
        total++;     
        if(total == n-1) break; 
    }  
    printf("%d\n%d\n", data[i].dis, n-1); 
    for(j = 0; j <= i; j++)    
        if(used[j])
             printf("%d %d\n", data[j].begin, data[j].end); 
     return 0; 
 }

dijsktra

#include <iostream> 
#include <memory> 
using namespace std; 

const int maxint = 9999999; 
const int maxn = 1010;  
int data[maxn][maxn], lowcost[maxn]; //data存放点点之间的距离,lowcost存放点到start的距离,从0开始存放 
bool used[maxn]; //标记点是否被选中 
int n; //顶点的个数

void disktra(int start)//初始点是start的dij算法 
{  
    int i,j;  
    memset(used, 0, sizeof(used)); 
    //inite  
    for(i = 0; i < n; i++)     
        lowcost[i] = data[start][i]; 
    used[start] = true; 
    lowcost[start] = 0;  
    for(i = 0; i < n-1; i++) 
    {     
        //choose min 
        int tempmin = maxint;    
        int choose;     
        for(j = 0; j < n; j++)    
        {      
            if(!used[j] && tempmin > lowcost[j])     
            {       
                choose = j;       
                tempmin = lowcost[j];     
            }    
        }     
        used[choose] = true;    //updata others    
        for(j = 0; j < n; j++) 
        {      
            if(!used[j] && data[choose][j] < maxint && lowcost[choose]+data[choose][j] < lowcost[j])   
                lowcost[j] = lowcost[choose]+data[choose][j];    
        } 
    } 
}

并查集模板

#include <iostream> 
#include <memory> 
using namespace std;

const int MAX = 5005;  
class UFSet 
{  
private:  
    int parent[MAX+1]; 
    int size; 
public:  
    UFSet(int s = MAX);//初始化  
    void Union(int root1, int root2);//合并,注意参数为根节点 
    int Find(int i );//返回根节点 
    int SetNum();//返回集合的个数 
};  

UFSet::UFSet(int s)
{  
    size = s+1;  
    memset(parent, -1, sizeof(int)*size ); 
}  

void UFSet::Union( int root1, int root2) 
{ 
    int temp = parent[root1]+parent[root2]; 
    if(parent[root1]<parent[root2]) 
    {     
        parent[root2]=root1;    
        parent[root1]=temp; 
    } 
    else 
    {     
        parent[root1]=root2;
        parent[root2]=temp; 
    } 
}  

int UFSet::Find(int i) 
{  
    int j;  
    for(j = i; parent[j]>=0; j = parent[j]); 
    while(i!=j) 
    {     
        int temp = parent[i];    
        parent[i] = j; 
        i = temp; 
    }  
    return j; 
}  

int UFSet::SetNum() 
{  
    int totalNum = 0,i;
    for(i = 0; i < size; i++)    
        if(parent[i] < 0)     
            totalNum++; return totalNum; } 

高精度模板

#include <string> 
#include <algorithm> 
using namespace std;  

// ----------------- 非负数计算部分:f1~f14 
-------------------------------------  
string operator+(string x, string y); // x、y都必须非负 
string operator-(string x, string y); // x、y都必须非负(结果可能为负) 
string operator*(string x, string y); // x、y非负  
string operator*(string s, int a); // s,a非负,且a必须小于2*10^8. 

string MSDiv(string x, int y, int &res); // 多精度除以int,x非负,y为正  
string operator/(string s, int a); // 调用MSDiv 
int operator%(string s, int a); // 调用MSDiv
string MMDiv(string x, string y, string &res); // 多精度除以多精度,x非负,y为正

string operator/(string x, string y); // 调用MMDiv 
string operator%(string x, string y); // 调用MMDiv 

string HPower(string s, int a); // s,a必须非负! 
string HSqrt(string s); // 开平方取整,s非负!  
string Head_zero_remover(string num); // 除了开头可能有'0'外,num必须是非负数。  
bool Less(string x, string y); // 非负数之间的“小于”

// ----------------- 以下是负数支持:f15~f19 
------------------------------------ 
string operator-(string s); // 取负 
string SAdd(string x, string y); 
string SMinus(string x, string y); 
string SMul(string x, string y);
string SMul(string s, int a); // 同样,a的绝对值不能超过2*10^8 

// ----------------- f1 () -------------------------- string operator+(string x, string y) 
{  
    if(x.size() < y.size()) // 预处理,保证x的实际长度>=y
    x.swap(y);  
    y.insert(y.begin(), x.size()-y.size(), '0'); // y开头补0到和x一样长 

    string sum(x.size(), -1); // 初始大小:x.size() 

    int carry=0;  

    for(int i=x.size()-1; i >= 0; --i) 
    {  
        carry += x[i]+y[i]-2*'0'; 
        sum[i] = carry%10+'0'; 
        carry /= 10;
    }

    if(carry > 0) // 还有进位1  
        return string("1") += sum; // 给开头添加一个“1”  
    return sum; 
}    

// ----------------- f2 (need: f13, f14) -------------------- 
string operator-(string x, string y) 
{  
    bool neg = false; // 结果为负标志
    if(Less(x, y)) 
    {  
        x.swap(y); // 如果x<y,交换 
        neg = true; // 结果标记为负 
    }   
    string diff(x.size(), -1); // 差(结果)  
    y.insert(y.begin(), x.size()-y.size(), '0'); 
    int carry=0;  
    for(int i=x.size()-1; i >= 0; --i) 
        if(x[i] >= y[i]+carry) // 本位够减 
        {     
            diff[i] = x[i]-y[i]-carry+'0';    
            carry = 0; 
        }  
        else // 需要借位
        {     
            diff[i] = 10+x[i]-y[i]-carry+'0';   
            carry=1; 
        }  
    if(neg)  
        return string("-")+=Head_zero_remover(diff); 
    return Head_zero_remover(diff);  
}    

// ----------------- f3 (need f1, f4) ------------------------
string operator*(string x, string y) 
{  
    string prod="0"; //初值:0  
    for(int i=y.size()-1; i >= 0; --i) 
    {          
        string p_sum = x * (y[i]-'0'); // p_sum:部分积
        if(p_sum != "0") // 保证后面加0后也符合UAdd的要求!  
        p_sum.insert(p_sum.end(), y.size()-1-i, '0');
        prod = prod + p_sum; 
    }   
    return prod; 
}    

// ----------------- f4 () -------------------------- 
string operator*(string s, int a) 
{  
    if(s == "0" || a == 0) // 以免后面特殊处理! 
        return "0";   
    string prod(s.size(), -1); // 先申请s.size()位   
    int carry=0;  
    for(int i=s.size()-1; i >= 0; --i) 
    {  
        carry += (s[i]-'0')*a; 
        prod[i] = carry%10+'0'; 
        carry /= 10; 
    }  
    while(carry>0) 
    {
        prod.insert(prod.begin(), carry%10+'0'); 
        carry /= 10; 
    }  
    return prod; 
}    

// ----------------- f5 (need f13) -------------------------- 
string MSDiv(string x, int y, int &res) 
{  
    string quot(x.size(), 0);  
    res=0;  
    for(int i=0; i<x.size(); ++i) 
    {  
         res = 10*res+x[i]-'0'; 
         quot[i] = res/y+'0'; // 整除结果为商 
         res %= y; // 取余保留 
     }  
     return Head_zero_remover(quot); 
}    


// ----------------- f6 (need f5, f13) ------------------------ 
string operator/(string s, int a) 
{  
    int res; 
    return MSDiv(s, a, res); 
}    

// ----------------- f7 (need f5, f13) ------------------------ 
int operator%(string s, int a) 
{  
    int res;  
    MSDiv(s, a, res);  
    return Head_zero_remover(res); 
}    

// ----------------- f8 (need f2, f13, f14) ------------------ 
string MMDiv(string x, string y, string &res) 
{  
    string quot(x.size(), '0'); // 初始化成全'0'
    res = ""; // 初始为空,每次下移一个字符 
    for(int i=0; i<x.size(); ++i) 
    {  
        res += x[i]; // 等价
        res = res*10+x[i];(注意:不是加) 
        while( ! Less(res, y)) // 余数大于等于除数时... 
        {     
            res = res - y; // 余数减去除数    
            ++quot[i]; // 商对应位加1 
        } 
    }  
    return Head_zero_remover(quot); 
}    

// ----------------- f9 (need f2, f8, f13, f14) ------------
string operator/(string x, string y) 
{  
    return MMDiv(x, y, string()); 
}    

// ----------------- f10 (need f2, f8, f13, f14) -------------- 
string operator%(string x, string y) 
{  
    string res;
    MMDiv(x, y, res); 
    return res; 
}    

// ----------------- f11 (need f1, f3, f4) --------------------
string HPower(string s, int a) // 最多做2*ln(a)次大数乘法 
{  
    string power="1"; 
    while(a>0) 
    {  
        if(a%2 == 1)     
            power = power * s; 
        a /= 2; 
        s = s * s; 
    } 
    return power; 
}  

// ----------------- f12 (need f2, f4, f13, f14) -------------  
string HSqrt(string s) 
    // 手工开平方。若要返回余数,return前的res就是! 
{  
    string sqroot((s.size()+1)/2, -1);  
    string res = s.substr(0, 2-s.size()%2); // 奇位取前1,偶位取前2 
    string div="0"; // 占一位置  
    for(int i=0; i<sqroot.size(); ++i) 
    {  
        for(int quot=9;  --quot) 
        {     
            div[div.size()-1] = quot+'0'; // 末位试商,从'9'到'0'    
            string p_prod = div*quot;     
            if( ! Less(res, p_prod) ) // p_prod <= res 
            {      
                sqroot[i] = quot+'0'; // 将结果追加!
                div = sqroot.substr(0, i+1)*20;     
                res = res - p_prod;           
                string next2 = s.substr((i+1)*2-s.size()%2, 2);     
                if(res == "0")  res = next2; // 取后2位
                else  res += next2; 
                    // 下移2位,追加;即res = res*100+next2 
                break;    
            } 
        } 
    }  
    return sqroot; 
}    


// ----------------- f13 () -------------------------- bool Less(string x, string y) 
{  
    return x.size()<y.size() || x.size() == y.size() && x < y; 
}    

// ----------------- f14 () -------------------------- string Head_zero_remover(string num) // 化简“003”等数
{  
    if(num[0] != '0') return num;  
    int pos=num.find_first_not_of('0'); 
    if(pos == string::npos) // 全0 
        return "0";  
    return num.substr(pos, num.size()-pos); 
}    
/////////////////////////////////////////////////////// 
                 以下是负数支持!
///////////////////////////////////////////////////////

// ----------------- f15 () --------------------------
string operator-(string s) 
{  
    if(s[0] == '-')  return s.substr(1, s.size()-1); 
    if(s == "0") return "0";  
}    

// ----------------- f16 (need f1, f2, f13, f14, f15) ---------
string SAdd(string x, string y) 
{  
    if(x[0] == '-' && y[0] == '-') return -(-x + -y);
    if(x[0] == '-') return y - -x; 
    if(y[0] == '-') return x - -y; 
    return x + y; 
}    

// ----------------- f17 (need f1, f2, f13, f14, f15) --------- 
string SMinus(string x, string y) 
{  
    if(x[0] == '-' && y[0] == '-')
        return -y - -x; 
    if(x[0] == '-') 
        return -(-x + y); 
    if(y[0] == '-') 
        return x + -y; 
    return x - y; 
}    

// ----------------- f18 (need f1, f3, f4, f15) ---------------
string SMul(string x, string y) 
{  
    if(x[0] == '-' && y[0] == '-') 
        return (-x)*(-y); 
    if(x[0] == '-')
        return -((-x)*y); 
    if(y[0] == '-') 
        return -(x*(-y));     
    return x * y; 
}    

// ----------------- f19 (need f4, f15)------------------------ 
string SMul(string s, int a) 
{  
    if(s[0] == '-' && a<0) 
        return (-s)*(-a); 
    if(s[0] == '-') 
        return -((-s)*a); 
    if(a<0)  
        return -(s*(-a)); 
    return s * a; 
} 
ACM 算法模板集 Contents 一. 常用函数与STL 二. 重要公式与定理 1. Fibonacci Number 2. Lucas Number 3. Catalan Number 4. Stirling Number(Second Kind) 5. Bell Number 6. Stirling's Approximation 7. Sum of Reciprocal Approximation 8. Young Tableau 9. 整数划分 10. 错排公式 11. 三角形内切圆半径公式 12. 三角形外接圆半径公式 13. 圆內接四边形面积公式 14. 基础数论公式 三. 大数模板,字符读入 四. 数论算法 1. Greatest Common Divisor最大公约数 2. Prime素数判断 3. Sieve Prime素数筛法 4. Module Inverse模逆元 5. Extended Euclid扩展欧几里德算法 6. Modular Linear Equation模线性方程(同余方程) 7. Chinese Remainder Theorem中国余数定理(互素于非互素) 8. Euler Function欧拉函数 9. Farey总数 9. Farey序列构造 10. Miller_Rabbin素数测试,Pollard_rho因式分解 五. 图论算法 1. 最小生成树(Kruscal算法) 2. 最小生成树(Prim算法) 3. 单源最短路径(Bellman-ford算法) 4. 单源最短路径(Dijkstra算法) 5. 全源最短路径(Folyd算法) 6. 拓扑排序 7. 网络预流和最大流 8. 网络最小费用最大流 9. 网络最大流(高度标号预流推进) 10. 最大团 11. 二分图最大匹配(匈牙利算法) 12. 带权二分图最优匹配(KM算法) 13. 强连通分量(Kosaraju算法) 14. 强连通分量(Gabow算法) 15. 无向图割边割点和双连通分量 16. 最小树形图O(N^3) 17. 最小树形图O(VE) 六. 几何算法 1. 几何模板 2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 七. 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. 逆序数(归并排序) 8. 树状DP 9. 欧拉路 10. 八数码 11. 高斯消元法 12. 字符串匹配(KMP算法) 13. 全排列,全组合 14. 二维线段树 15. 稳定婚姻匹配 16. 后缀数组 17. 左偏树 18. 标准RMQ-ST 19. 度限制最小生成树 20. 最优比率生成树(0/1分数规划) 21. 最小花费置换 22. 区间K大数 23. LCA - RMQ-ST 24. LCA – Tarjan 25. 指数型母函数 26. 指数型母函数(大数据) 27. 单词前缀树(字典树+KMP) 28. FFT(大数乘法) 29. 二分图网络最大流最小割 30. 混合图欧拉回路 31. 无源汇上下界网络流 32. 二分图最小点权覆盖 33. 带约束的轨道计数(Burnside引理) 34. 三分法求函数波峰 35. 单词计数,矩阵乘法 36. 字符串和数值hash 37. 滚动队列,前向星表示法 38. 最小点基,最小权点基
用于打比赛的ACM算法模板 常用函数与STL 重要公式与定理 1. Fibonacci Number 2. Lucas Number 3. Catalan Number 4. Stirling Number(Second Kind) 5. Bell Number 6. Stirling's Approximation 7. Sum of Reciprocal Approximation 8. Young Tableau 9. 整数划分 10. 错排公式 11. 三角形内切圆半径公式 12. 三角形外接圆半径公式 13. 圆內接四边形面积公式 14. 基础数论公式 大数模板,字符读入 数论算法 1. Greatest Common Divisor最大公约数 2. Prime素数判断 3. Sieve Prime素数筛法 4. Module Inverse模逆元 5. Extended Euclid扩展欧几里德算法 6. Modular Linear Equation模线性方程(同余方程) 7. Chinese Remainder Theorem中国余数定理(互素于非互素) 8. Euler Function欧拉函数 9. Farey总数 9. Farey序列构造 10. Miller_Rabbin素数测试,Pollard_rho因式分解 图论算法 1. 最小生成树(Kruscal算法) 2. 最小生成树(Prim算法) 3. 单源最短路径(Bellman-ford算法) 4. 单源最短路径(Dijkstra算法) 5. 全源最短路径(Folyd算法) 6. 拓扑排序 7. 网络预流和最大流 8. 网络最小费用最大流 9. 网络最大流(高度标号预流推进) 10. 最大团 11. 二分图最大匹配(匈牙利算法) 12. 带权二分图最优匹配(KM算法) 13. 强连通分量(Kosaraju算法) 14. 强连通分量(Gabow算法) 15. 无向图割边割点和双连通分量 16. 最小树形图O(N^3) 17. 最小树形图O(VE) 几何算法 1. 几何模板 2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. 逆序数(归并排序) 8. 树状DP 9. 欧拉路 10. 八数码 11. 高斯消元法 12. 字符串匹配(KMP算法) 13. 全排列,全组合 14. 二维线段树 15. 稳定婚姻匹配 16. 后缀数组 17. 左偏树 18. 标准RMQ-ST 19. 度限制最小生成树 20. 最优比率生成树(0/1分数规划) 21. 最小花费置换 22. 区间K大数 23. LCA - RMQ-ST 24. LCA – Tarjan 25. 指数型母函数 26. 指数型母函数(大数据) 27. 单词前缀树(字典树+KMP) 28. FFT(大数乘法) 29. 二分图网络最大流最小割 30. 混合图欧拉回路 31. 无源汇上下界网络流 32. 二分图最小点权覆盖 33. 带约束的轨道计数(Burnside引理) 34. 三分法求函数波峰 35. 单词计数,矩阵乘法 36. 字符串和数值hash 37. 滚动队列,前向星表示法 38. 最小点基,最小权点基
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值