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; 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 图论 3 1.1 术语 3 1.2 独立集、覆盖集、支配集之间关系 3 1.3 DFS 4 1.3.1 割顶 6 1.3.2 桥 7 1.3.3 强连通分量 7 1.4 最小点基 7 1.5 拓扑排序 7 1.6 欧拉路 8 1.7 哈密顿路(正确?) 9 1.8 Bellman-ford 9 1.9 差分约束系统(用bellman-ford解) 10 1.10 dag最短路径 10 1.11 二分图匹配 11 1.11.1 匈牙利算法 11 1.11.2 KM算法 12 1.12 网络流 15 1.12.1 最大流 15 1.12.2 上下界的网络的最大流 17 1.12.3 上下界的网络的最小流 17 1.12.4 最小费用最大流 18 1.12.5 上下界的网络的最小费用最小流 21 2 数论 21 2.1 最大公约数gcd 21 2.2 最小公倍数lcm 22 2.3 快速幂取模B^LmodP(O(logb)) 22 2.4 Fermat小定理 22 2.5 Rabin-Miller伪素数测试 22 2.6 Pollard-rho 22 2.7 扩展欧几里德算法extended-gcd 24 2.8 欧拉定理 24 2.9 线性同余方程ax≡b(mod n) 24 2.10 中国剩余定理 25 2.11 Discrete Logging(BL == N (mod P)) 26 2.12 N!最后一个不为0的数字 27 2.13 2^14以内的素数 27 3 数据结构 31 3.1 堆(最小堆) 31 3.1.1 删除最小值元素: 31 3.1.2 插入元素和向上调整: 32 3.1.3 堆的建立 32 3.2 并查集 32 3.3 树状数组 33 3.3.1 LOWBIT 33 3.3.2 修改a[p] 33 3.3.3 前缀和A[1]+…+A[p] 34 3.3.4 一个二维树状数组的程序 34 3.4 线段树 35 3.5 字符串 38 3.5.1 字符串哈希 38 3.5.2 KMP算法 40 4 计算几何 41 4.1 直线交点 41 4.2 判断线段相交 41 4.3 三点外接圆圆心 42 4.4 判断点在多边形内 43 4.5 两圆交面积 43 4.6 最小包围圆 44 4.7 经纬度坐标 46 4.8 凸包 46 5 Problem 48 5.1 RMQ-LCA 48 5.1.1 Range Minimum Query(RMQ) 49 5.1.2 Lowest Common Ancestor (LCA) 53 5.1.3 Reduction from LCA to RMQ 56 5.1.4 From RMQ to LCA 57 5.1.5 An algorithm for the restricted RMQ 60 5.1.6 An AC programme 61 5.2 最长公共子序列LCS 64 5.3 最长上升子序列/最长不下降子序列(LIS) 65 5.3.1 O(n^2) 65 5.3.2 O(nlogn) 66 5.4 Joseph问题 67 5.5 0/1背包问题 68 6 组合数学相关 69 6.1 The Number of the Same BST 69 6.2 排列生成 71 6.3 逆序 72 6.3.1 归并排序求逆序 72 7 数值分析 72 7.1 二分法 72 7.2 迭代法(x=f(x)) 73 7.3 牛顿迭代 74 7.4 数值积分 74 7.5 高斯消元 75 8 其它 77

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值