[置顶] 个人模板记录♪(^∇^*)♪(^∇^*)♪(^∇^*)

1、KMP

int next[2005];
int lena;
int lenb;

void set_naxt()//子串的next数组
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<lenb)
    {
        if(j==-1||b[i]==b[j])
        {
            i++; j++;
            next[i]=j;
        }
        else
        j=next[j];
    }
}

int kmp()
{
    int i=0,j=0;
    set_naxt();
    while(i<lena)
    {
        if(j==-1||a[i]==b[j])
        {
            i++;j++;
        }
        else
        j=next[j];
        if(j==lenb)
        return i-j+1;
    }
    return -1;
}
2、归并排序

void mergesort(int l,int r)  
{  
    int i,j,k,m;  
    if(l<r)  
    {  
        m=(r+l)>>1;  
        mergesort(l,m);  
        mergesort(m+1,r);  
        k=l;  
        for(i=l,j=m+1; i<=m&&j<=r;)  
        {  
            if(a[i]>a[j])  
            {  
                b[k++]=a[j++];
		//cont+=m-(i-1);//相当于线性交换了这么多次  
            }  
            else b[k++]=a[i++];  
        }  
        while(i<=m)b[k++]=a[i++];  
        while(j<=r)b[k++]=a[j++];  
        for(i=l; i<=r; i++)a[i]=b[i];  
    }  
}  
3、快速排序

void quicksort(int l,int r)
{
    int i,j,tmp,t;
    if(l>r)return ;
    tmp=a[l];i=l,j=r;
    while(i!=j)
    {
        while(a[j]>=tmp&&i<j)j--;
        while(a[i]<=tmp&&i<j)i++;
        if(i<j)
        {
            t=a[i];a[i]=a[j];a[j]=t;
        }
    }
    a[l]=a[i];
    a[i]=tmp;
    quicksort(l,i-1);
    quicksort(i+1,r);
}
4、多重背包(包含01背包,完全背包)

void zoreonepack(int val,int cost)
{
    for(int i=v;i>=cost;i--)
    {
        if(dp[i-cost]+val>dp[i])
        {
            dp[i]=dp[i-cost]+val;
        }
    }
}
void completepack(int val,int cost)
{
    for(int i=cost;i<=v;i++)
    {
        dp[i]=max(dp[i],dp[i-cost]+val);
    }
}
void multipack(int val,int cost,int num)
{
    if(num*cost>=v)
    {
        completepack(val,cost);
    }
    else
    {
        int k=1;
         while(k<num)
         {
             zoreonepack(k*val,k*cost);
             num-=k;k+=k;
         }
         zoreonepack(num*val,num*cost);
    }
}
5、二维0-1背包

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;

int weight[3405],value[3405],dp[3405][12890];

void solve(int n,int w)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=w;j++)
        {
            if(weight[i]>j)
            {
                dp[i][j] = dp[i-1][j];//买不了所以直接继承
            }
            else
            {
                dp[i][j]=max(dp[i-1][j-weight[i]]+value[i],dp[i-1][j]);
            }
        }
    }
    cout<<dp[n][w]<<endl;
}

int main()
{
    int n,w;

    while(cin>>n>>w)
    {
        memset(dp,0,sizeof(dp));

        for(int i=1;i<=n;i++)
        {
            cin>>weight[i]>>value[i];
        }
        solve(n,w);
    }
    return 0;
}
6、哈希表

const int maxn=100000;  
const int hashh=1000007;  

struct hashmap
{
    ll a[maxn];
    int head[hash];
    int next[maxn];
    int size;
    void init()
    {
        memset(head,-1,sizeof(head));
        size=0;
    }
    bool find(ll val)
    {
        int tmp=(val%hash+hash)%hash;
        for(int i=head[tmp];i!=-1;i=next[i])
        {
            if(val==a[i])return true;
        }
        return false;
    }
    void add(ll val)
    {
        int tmp=(val%hash+hash)%hash;
        if(find(val))return ;
        a[size]=val;
        next[size]=head[tmp];//令next指向-1、
        head[tmp]=size++;
    }
}h1,h2;
7、叉乘

double chacheng(Point p1, Point p2, Point p3)
{
    return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}

8、矩阵快速幂(POJ 3070 求斐波那契数列)

#include<stdio.h>  
#include<iostream>  
#include<string.h>  
using namespace std;  
#define mod 10000  
typedef struct Matrix  
{  
    int mat[2][2];  
}matrix;  
matrix A,B;  
Matrix matrix_mul(matrix a,matrix b)矩阵乘法  
{  
    matrix c;  
    memset(c.mat,0,sizeof(c.mat));  
    int i,j,k;  
    for(int i=0;i<2;i++)  
    {  
        for(int j=0;j<2;j++)  
        {  
            for(int k=0;k<2;k++)  
            {  
                c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];  
                c.mat[i][j]%=mod;  
            }  
        }  
    }  
    return c;  
}  
Matrix matrix_quick_power(matrix a,int k)//矩阵快速幂0.0  
{  
    matrix b;  
    memset(b.mat,0,sizeof(b.mat));  
    for(int i=0;i<2;i++)  
    b.mat[i][i]=1;//单位矩阵b  
    while(k)  
    {  
        if(k%2==1)  
        {  
            b=matrix_mul(a,b);  
            k-=1;  
        }  
        else  
        {  
            a=matrix_mul(a,a);  
            k/=2;  
        }  
    }  
    return b;  
}  
int main()  
{  
    int n;  
    while(cin>>n)  
    {  
        if(n==-1)break;  
        A.mat[0][0]=1;A.mat[0][1]=1;//我们通过推论得到的矩阵A  
        A.mat[1][0]=1;A.mat[1][1]=0;  
        B=matrix_quick_power(A,n);  
        cout<<B.mat[0][1]<<endl;//根据推论得出,这个位子上的数据是我们最终需要的数据。  
        /*for(int i=0;i<2;i++) 
        { 
            for(int j=0;j<2;j++) 
            { 
                cout<<B.mat[i][j]<<" "; 
            } 
            cout<<endl; 
        }*/  
    }  
}  
9、树状数组

int tree[100005];//树
int lowbit(int x)//lowbit
{
    return x&(-x);
}
int sum(int x)//求和求的是比当前数小的数字之和,至于这里如何实现,很简单:int sum=sum(a[i]);
{
    int sum=0;
    while(x>0)
    {
        sum+=tree[x];
        x-=lowbit(x);
    }
    return sum;
}
void add(int x,int c)//加数据。
{
    while(x<=n)
    {
        tree[x]+=c;
        x+=lowbit(x);
    }
}
10、二维树状数组

int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,int d)
{
    int temp=y;
    while(x<=m)
    {
        y=temp;
        while(y<=m)
        {
            a[x][y]+=d;
            y=y+lowbit(y);
        }
        x=x+lowbit(x);

    }

}
int getsum(int x,int y)
{
    int sum=0;
    int temp=y;
    while(x>0)
    {
        y=temp;
        while(y>0)
        {
            sum=sum+a[x][y];
            y=y-lowbit(y);
        }
        x=x-lowbit(x);
    }
    return sum;

}
update(x+1,y+1,d);

11、线段树

#define lson l,m,rt*2
#define rson m+1,r,rt*2+1

void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int Query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return tree[rt];
    }
    else
    {
        int m=(l+r)>>1;
        int ans=0;
        if(L<=m)
        {
            ans+=Query(L,R,lson);
        }
        if(m<R)
        {
            ans+=Query(L,R,rson);
        }
        return ans;
    }
}
void build( int l ,int r , int rt )
{
	if( l == r )
	{
		scanf("%d",&tree[rt]);
		return ;
	}
	else
	{
		int m = (l+r)>>1 ;
		build(lson) ;
		build(rson) ;
		pushup(rt) ;
	}
}
void update(int p,int c,int l,int r,int rt)//p阵营c数据.
{
    //printf("%d %d %d %d %d\n",p,c,l,r,rt);
    if(l==r)
    {
        tree[rt]+=c;
    }
    else
    {
        int m=(l+r)>>1;
        if(p<=m) update(p,c,lson);
        else  update(p,c,rson);
        pushup(rt);
		//printf("sum[%d]:%d\n",rt,tree[rt]);
    }
}
int query(int L, int R, int l, int r, int rt, int *pos)//返回位子
{
    if (L <= l && r <= R)
    {
        *pos = posn[rt];
        return tree[rt];
    }
    else
    {
        int m = (l + r) >> 1;
        int ret1 = INT_MIN;
        int ret2 = INT_MIN;
        int pa, pb;
        int *pos1 = &pa;
        int *pos2 = &pb;
        if (L <= m)
        {
            ret1 = query(L, R,  lson, pos1);
        }
        if (R > m)
        {
            ret2 = query(L, R, rson, pos2);
        }
        if (ret1 > ret2)
        {
            *pos = pa;
        }
        else
        {
            *pos = pb;
            ret1 = ret2;
        }
        return ret1;
    }
}
int pos;
printf("%d %d\n", pos, query(1, n, 1, n, 1, &pos));
12、线段树2(区间更新很好的模板)

#include<stdio.h>
#include<string.h>
using namespace std;
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
#define ll long long int
ll tree[1212112];
ll flag[1212112];
void pushdown(int l,int r,int rt)//向下维护树内数据
{
    if(flag[rt])//如果贪婪标记不是0(说明需要向下进行覆盖区间(或点)的值)
    {
        int m=(l+r)/2;
        flag[rt*2]+=flag[rt];
        flag[rt*2+1]+=flag[rt];
        tree[rt*2]+=(m-l+1)*flag[rt];//千万理解如何覆盖的区间值(对应线段树的图片理解(m-l)+1)是什么意识.
        tree[rt*2+1]+=(r-(m+1)+1)*flag[rt];
        flag[rt]=0;
    }
}
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build( int l ,int r , int rt )
{
	if( l == r )
	{
		scanf("%lld",&tree[rt]);
		return ;
	}
	else
	{
		int m = (l+r)>>1 ;
		build(lson) ;
		build(rson) ;
		pushup(rt) ;
		return ;
	}
}
ll Query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return tree[rt];
    }
    else
    {
        pushdown(l,r,rt);
        int m=(l+r)>>1;
        ll ans=0;
        if(L<=m)
        {
            ans+=Query(L,R,lson);
        }
        if(m<R)
        {
            ans+=Query(L,R,rson);
        }
        return ans;
    }
}
void update(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&r<=R)//覆盖的是区间~
    {
        tree[rt]+=c*((r-l)+1);//覆盖当前点的值
        flag[rt]+=c;//同时懒惰标记~!
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(L<=m)
    {
        update(L,R,c,lson);
    }
    if(m<R)
    {
        update(L,R,c,rson);
    }
    pushup(rt);
}
int main()
{
     int n,m;
     while(~scanf("%d%d",&n,&m))
     {
         memset(flag,0,sizeof(flag));
         memset(tree,0,sizeof(tree));
         build(1,n,1);
         for(int i=0;i<m;i++)
         {
             char s[5];
             int x,y;
             scanf("%s%d%d",s,&x,&y);
             if(s[0]=='Q')
             {
                 printf("%lld\n",Query(x,y,1,n,1));
             }
             if(s[0]=='C')
             {
                 ll c;
                 scanf("%lld",&c);
                 update(x,y,c,1,n,1);
             }
         }
     }
}

13、字典树1

void creattrie(char *str)
{
    int len=strlen(str);
    tire *p=root,*q;
    for(int i=0;i<len;i++)
    {
        int id=str[i]-'0';
        if(p->next[id]==NULL)
        {
            q=(trie *)malloc(sizeof(trie));
            q->v=1;
            for(int j=0;j<maxn;j++)
            {
                q->next[j]=NULL;
            }
            p->next[id]=q;
            p=p->next[id];
        }
        else 
        {
            p->next[id]->v++;
            p=p->next[id];
        }
    }
    p->v=-1;
}
int findtrie(char *str)
{
    int len=strlen(str);
    trie *p=root;
    for(int i=0;i<maxn;i++)
    {
        int id=str[i]-'0';
        p=p->next;
        if(p==NULL)
        return 0;
        if(p->v==-1)
        {
            return -1;
        }
    }
    return -1;
}
int dealTrie(Trie* T)
{
    int i;
    if(T==NULL)
        return 0;
    for(i=0;i<MAX;i++)
    {
        if(T->next[i]!=NULL)
            deal(T->next[i]);
    }
    free(T);
    return 0;
}
14、做题更实用的字典树

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
#define maxn 26//只包含小写字母、
typedef struct tree
{
    int flag;
    tree *next[maxn];
    char  la[30];
}tree;
tree root;

void creat(char *str)
{
    int len=strlen(str);
    tree *p=&root,*q;
    for(int i=0;i<len;i++)
    {
        int id=str[i]-'a';
        if(p->next[id]==NULL)
        {
            q=(tree *)malloc(sizeof(root));
            q->v=1;
            for(int j=0;j<26;j++)
            {
                q->next[j]=NULL;
            }
            p->next[id]=q;
        }
        else
        {
            p->next[id]->v++;
        }
            p=p->next[id];
    }
}
int find(char *str)
{
    int len=strlen(str);
    tree *p=&root;
    for(int i=0;i<len;i++)
    {
        int id=str[i]-'a';
        p=p->next[id];
        if(p==NULL)
        return 0;
    }
    return p->v;
}
    char str[15];  
    int i;  
    for(int i=0;i<26;i++)  
    {  
        root.next[i]=NULL;  
    }  
void Freedom(tree* p)
{
    int i;
    for(i=0;i<52;i++){
        if(p->next[i]!=NULL)
            Freedom(p->next[i]);
    }
    free(p);
}
        Freedom(&root);

15、prim

void prim()
{
	int i,j,k,min;
	for(i=2;i<=n;i++)
		dis[i]=map[1][i];
	vis[1]=1;
	for(i=2;i<=n;i++)//经过N次遍历一定能遍历所有的点 也就是完成了最终目标.
	{
		min=inf;
		for(j=1;j<=n;j++)
		{
			if(vis[j]==0 &&dis[j]<min)
			{
				min=dis[j];
				k=j;
			}
		}
		if(min==inf)
			break;
		vis[k]=1;
		sum+=sqrt(1.0*min);//完成了一次权值加和.
		for(j=2;j<=n;j++)
		{
			if(vis[j]==0 &&dis[j]>map[k][j])
				dis[j]=map[k][j];
		}//更新最优解.
	}

}
16、并查集

int find(int a)
{
    int r=a;
    while(f[r]!=r)
    r=f[r];
    int i=a;
    int j;
    while(i!=r)
    {
        j=f[i];
        f[i]=r;
        i=j;
    }
    return r;
}
int find(int x)
{
    return f[x] == x ? x : (f[x] = find(f[x]));
}
void merge(int a,int b)
{
    int A,B;
    A=find(a);
    B=find(b);
    if(A!=B)
    f[B]=A;
}

17、带权并查集

#include<stdio.h>
#include<string.h>
using namespace std;
int f[1000010];
int sum[1000010];
int find(int x)
{
    if(x!=f[x])
    {
        int pre=f[x];//pre是x的一个父节点。
        f[x]=find(f[x]);//递归找祖先。
        sum[x]+=sum[pre];
    }
    return f[x];
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<=n;i++)
        {
            f[i]=i;
            sum[i]=0;
        }
        int op;
        while(n--)
        {
            scanf("%d",&op);
            if(op==1)
            {
                int x,y,val;
                scanf("%d%d%d",&x,&y,&val);
                int X=find(x);
                int Y=find(y);
                if(X!=Y)
                {
                    sum[Y]=val-sum[y]+sum[x];
                    f[Y]=X;
                }
            }
            else 
            {
                int x,y;
                scanf("%d%d",&x,&y);
                int X=find(x);
                int Y=find(y);
                if(X!=Y)
                {
                    printf("?\n");
                }
                else
                {
                    printf("%d\n",sum[y]-sum[x]);
                }
            }
        }
    }
}

18、二分匹配

#include<stdio.h>  
#include<string.h>  
using namespace std;  
const int maxn = 505;  
  
int map[maxn][maxn];              //图的数组.  
int vis[maxn];                  //标记数组.  
int pri[maxn];  
int k,m,n;  
int  find(int x)  
{  
    for(int i=1;i<=m;i++)  
    {  
        if(vis[i]==0&&map[i][x])  
        {  
            vis[i]=1;  
            if(pri[i]==-1||find(pri[i]))  
            {  
                pri[i]=x;  
                return 1;  
            }  
        }  
    }  
    return 0;  
}  
int main()  
{  
    while(~scanf("%d",&k))  
    {  
        if(k==0)break;  
        scanf ("%d%d", &m, &n);  
        memset (map, 0, sizeof (map));  
        memset (pri, -1, sizeof (pri));  
        for(int i=0;i<k;i++)  
        {  
            int a,b;  
            scanf("%d%d",&a,&b);  
            map[a][b]=1;  
        }  
        int output=0;  
        for(int i=1;i<=n;i++)  
        {  
            memset(vis,0,sizeof(vis));  
            if(find(i))  
            output++;  
        }  
        printf("%d\n",output);  
    }  
}  

19、二分图染色

int bfs(int x)
{
    queue<int >s;
    int one=0;
    int two=0;
    s.push(x);
    color[x]=1;
    one++;
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        for(int i=0;i<map[u].size();i++)
        {
            int v=map[u][i];
            if(color[v])
            {
                if(color[v]==color[u])
                {
                    return 0;
                }
            }
            else
            {
                color[v]=3-color[u];
                if(color[v]==1)
                {
                    one++;
                }
                else
                {
                    two++;
                }
                s.push(v);
            }
        }
    }
    ans+=max(one,two);
    return 1;
}

20、邻接表(链式前向星)

#include<stdio.h>  
#include<string.h>  
using namespace std;  
int head[100000];  
struct EdgeNode  
{  
    int to;  
    int w;  
    int next;  
}e[100000];  
int n,u,v,w,m;  
int main()  
{  
    memset(head,-1,sizeof(head));  
    scanf("%d%d",&n,&m);  
    for(int i=0;i<m;i++)  
    {  
        scanf("%d%d%d",&u,&v,&w);  
        e[i].to=v;  
        e[i].w=w;  
        e[i].next=head[u];  
        head[u]=i;  
    }  
    for(int i=1;i<=n;i++)  
    {  
        printf("from: %d ",i);  
        for(int k=head[i];k!=-1;k=e[k].next)  
        {  
            printf("to:%d quanzhi:%d  ",i,e[k].to,e[k].w);  
        }  
        printf("\n");  
    }  
}  

21、邻接表(vector实现)

struct EdgeNode  
{  
    int to;  
    int w;  
};  
vector<EdgeNode>map[maxn];  
int main()  
{  
    int i,j,w,n,m,u,v;  
    EdgeNode e;  
    scanf("%d%d",&n,&m);  
    for(int i=0;i<m;i++)  
    {  
        scanf("%d%d%d",&u,&v,&w);  
        e.to=v;  
        e.w=w;  
        map[u].push_back(e);  
    }  
    printf("yes\n");  
    for(int i=1;i<=n;i++)  
    {  
        printf("i: %d ",i);  
        for(int j=0;j<map[i].size();j++)  
        {  
            printf("j: %d w: %d ",map[i][j].to,map[i][j].w);  
        }  
        printf("\n");  
    }  
}  

22、拓扑排序

#include<stdio.h>
#include<string.h>
using namespace std;
int map[1000][1000];
int degree[1000];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(map,0,sizeof(map));
        memset(degree,0,sizeof(degree));
        if(n==0&&m==0)break;
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(map[x][y]==0)
            {
                map[x][y]=1;
                degree[y]++;
            }
        }
        int cont=0;
        int flag=0;
        while(1)
        {
            int v;
            int ok=1;
            for(int i=0;i<n;i++)
            {
                if(degree[i]==0){v=i;ok=0;break;}
            }
            if(ok==1){flag=1;break;}
            degree[v]=-1;
            cont++;
            if(cont==n)break;
            for(int i=0;i<n;i++)
            {
                if(map[v][i]==1)
                {
                    map[v][i]=-1;
                    degree[i]--;
                }
            }
        }
        if(flag==1)
        {
            printf("NO\n");
        }
        else printf("YES\n");
    }
}

23、最大流FF

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int N=1005;
int pre[N];       //保存增广路径上的点的前驱顶点
bool vis[N];
int map[N][N];
int s,t;          //s为源点,t为汇点
int n,m;
bool bfs()
{
    int i,cur;
    queue<int >q;
    memset(pre,0,sizeof(pre));
    memset(vis,0,sizeof(vis));
    vis[s]=true;
    q.push(s);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        if(cur==t)return true;
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0&&map[cur][i])
            {
                q.push(i);
                pre[i]=cur;
                vis[i]=true;
            }
        }
    }
    return false;
}
int Max_Flow()
{
    int ans=0;
    while(1)
    {
        if(!bfs())return ans;
        int Min=0x3f3f3f3f;
        for(int i=t;i!=s;i=pre[i])
        {
            Min=min(Min,map[pre[i]][i]);
        }
        for(int i=t;i!=s;i=pre[i])
        {
            map[pre[i]][i]-=Min;
            map[i][pre[i]]+=Min;
        }
        ans+=Min;
    }
}
http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html
24、bellman最短路

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int dis[121212];
int u[121212];
int v[121212];
int w[121212];
int main()
{
    int n,m;
    int check;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0||m==0)break;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
        }
        for(int i=1;i<=n;i++)
        {
            dis[i]=0x1f1f1f1f;
        }
        dis[1]=0;
        for(int k=1;k<=n-1;k++)//最多遍历点的次数.
        {
            check=0;
            for(int i=1;i<=m;i++)
            {
                if(dis[v[i]]>dis[u[i]]+w[i])
                {
                    dis[v[i]]=dis[u[i]]+w[i];
                    check=1;
                }
                if(dis[u[i]]>dis[v[i]]+w[i])
                {
                    dis[u[i]]=dis[v[i]]+w[i];
                    check=1;
                }
            }
            if(check==0)break;
        }
        int flag=0;//标记是否有负权回路...
        for(int i=0;i<=m;i++)
        {
                if(dis[v[i]]>dis[u[i]]+w[i])
                {
                    dis[v[i]]=dis[u[i]]+w[i];
                    flag=1;
                }
                if(dis[u[i]]>dis[v[i]]+w[i])
                {
                    dis[u[i]]=dis[v[i]]+w[i];
                    flag=1;
                }
        }
        if(flag==1){printf("0\n");continue;}
        printf("%d\n",dis[n]);
    }
}
25、dij最短路

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define MAX(a,b) (a > b ? a : b)
#define MIN(a,b) (a < b ? a : b)
#define MAXN  10000001
#define INF 1000000007
int w[250][250];
int d[250];
int vis[250];
int n;
void dijkstra(int s)
{
    d[s]=0;
    for(int k=0;k<n;k++)
    {
        int m=INF;
        for(int i=0;i<n;i++)
        {
            if(!vis[i] && d[i]<=m)
                m=d[s=i];
        }
        vis[s] = 1;
        for(int i=0;i<n;i++)
        {
            d[i]=MIN(d[i],d[s]+w[s][i]);
        }
    }
}
int main()
{
    int m;
    while(~scanf("%d%d",&n,&m) && (n || m))
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            d[i]=INF;
            for(int j=0;j<n;j++)
            {
                w[i][j]=INF;
            }
        }
        int a,b,x;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&x);
            w[a-1][b-1] = w[b-1][a-1] = x;
        }
        dijkstra(0);
        printf("%d\n",d[n-1]);
    }
    return 0;
}
26、floyd求最小环

        int ans=0x1f1f1f1f;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                for(int k=j+1;k<i;k++)
                {
                    ans=min(ans,map[j][k]+dis[k][i]+dis[i][j]);
                }
            }
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++)
                {
                    map[j][k]=min(map[j][k],map[j][i]+map[i][k]);
                }
            }
        }
27、spfa
int SPFA(int s)
{
    int i;
    bool visit[N] = {false};
    int front = 0, rear = 1;
    memset(queue,0,sizeof(queue));
    for(i=1;i<=n;i++)
    d[i] = MAX;
    queue[front] = s;
    visit[s] = true;
    d[s] = 0;
    while(front<rear)
    {
        int u = queue[front];
        visit[u] = false;
        for(int i=1; i<=n; i++)
        {
            if (d[i]>d[u]+ edges[u][i])
            {
                d[i]= d[u]+edges[u][i];
                if( !visit[i] )
                {
                    visit[i] = true;
                queue[rear++] = i;
                }
            }
        }
        front++;
    }
    return 0;
}
28、更习惯实用的dij

void Dij()
{
	int i,j,k,v,tmp;
	memset(vis,0,sizeof(vis));
	for(i=1;i<=n;i++)//这里等号很魔怔
	    d[i]=w[1][i];//当然是要起点开始走.
	d[1]=0;
	vis[1]=1;
	for(i=1;i<=n;i++)//为了连接多少点的控制.//这里等号一样魔怔

	{
		tmp=N;
		for(j=1;j<=n;j++)
		{
			if(tmp>d[j]&&!vis[j])
			{
				tmp=d[j];
				v=j;
			}
		}//每次选中的都是距离起点最近的点.v
		vis[v]=1;
		for(k=1;k<=n;k++)
		{
			if(!vis[k])//然后松弛.
			d[k]=min(d[k],d[v]+w[v][k]);
		}
	}
}

29、优先队列优化+邻接表dij

#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<vector>
#include<queue>
const int maxn=30003;
const int INF=0x1f1f1f1f;
int n,m;
using namespace std;
struct Edge
{
    int from,to,dist;
    Edge(int u,int v,int d):from(u),to(v),dist(d) {}
};
string s;
string e;
vector<Edge>edges;//存储边的结点信息
vector<int>G[maxn];//邻接表
bool done[maxn];   //标记是否访问过
int d[maxn];    //距离数组
map<string,int>cnt;//映射成节点编号
struct heapnode //用于优先队列自定义
{
    int d,u;
    bool operator <(const heapnode rhs) const
    {
        return d > rhs.d;
    }
    heapnode(int dd,int uu):d(dd),u(uu) {}
};
void init()//初始化必不可少
{
    for(int i=0; i<n; i++)
        G[i].clear();
    edges.clear();
}
void dij( int s)
{
    priority_queue<heapnode>Q;
    for(int i=0; i<=n; i++)//初始化距离数组
        d[i]=INF;
    d[s]=0;
    memset(done ,0,sizeof(done));
    Q.push( heapnode(0,s) );
    while(!Q.empty())
    {
        heapnode x = Q.top();
        Q.pop();
        int u=x.u;
        if(u==cnt[e])
        {
            printf("%d\n",x.d);
            break;
        }
        if(done[u])continue;
        done[u] = true;
        for(int i=0; i<G[u].size(); i++)
        {
            Edge& e=edges[G[u][i]];//取出来一条邻接边
            if(d[e.to]>d[u]+e.dist)
            {
                d[e.to] = d[u] + e.dist;
                Q.push((heapnode(d[e.to],e.to)));
            }
        }
    }
}
void addedge(int from,int to,int dist)
{
    edges.push_back(Edge(from,to,dist));
    int m = edges.size();
    G[from].push_back(m-1);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int t=1;
        int ans=0;
        string str;
        init();
        for(int i=0; i<n; i++)
        {
            cin>>str;
            cnt[str]=t++;
        }
        for(int i=0; i<m; i++)
        {
            string str2;
            int x;
            cin>>str>>str2>>x;
            addedge(cnt[str],cnt[str2],x);
            addedge(cnt[str2],cnt[str],x);
        }
        cin>>s>>e;
        dij(cnt[s]);
        s.clear();
        e.clear();
        cnt.clear();
    }
    return 0;
}


30、最小树形图

#define INF 0x7fffffff  
double x[1000];  
double y[1000];  
double w[1000][1000];  
int flag[1000];//判断是否在有向环里边的缩点  
int vis[1000];  
int pre[1000];  
int n,m;  
void init()//不能少了初始化的内容  
{  
    memset(vis, 0, sizeof(vis));  
    memset(flag, 0, sizeof(flag));  
    for(int i=0; i<=n; i++)  
    {  
        w[i][i] = INF;  
        for(int j=i+1; j<=n; j++)  
            w[i][j]=w[j][i]=INF;  
    }  
}  
  
double directed_mst(int u)//u表示根节点  
{  
    double ans=0;  
    memset(vis, 0, sizeof(vis));  
    while(true)  
    {  
        //求最短弧集合E  
        for(int i=1; i<=n; i++)if(i!=u&&!flag[i])  
            {  
                w[i][i]=INF, pre[i] = i;  
                for(int j=1; j<=n; j++)if(!flag[j] && w[j][i]<w[pre[i]][i])  
                {  
                    pre[i] = j;  
                }  
                if(pre[i]==i)return -1;//也可以用dfs预处理判断凸的连通  
            }  
        //判断E是否有环  
        int i;  
        for(i=1; i<=n; i++)  
        {  
            if(i!=u&&!flag[i])  
            {  
                int j=i, cnt=0;  
                while(j!=u && pre[j]!=i && cnt<=n) j=pre[j], ++cnt;  
                if(j==u || cnt>n) continue; //最后能找到起点(根)或者是走过的点已经超过了n个,表示没有有向环  
                break;  
            }  
        }  
        if(i>n)  
        {  
            for(int i=1; i<=n; i++)if(i!=u && !flag[i]) ans+=w[pre[i]][i];  
            return ans;  
        }  
        //有环,进行收缩,把整个环都收缩到一个点i上。  
        int j=i;  
        memset(vis, 0, sizeof(vis));  
        do  
        {  
            ans += w[pre[j]][j], j=pre[j], vis[j]=flag[j]=true;//对环内的点标记,并且直接对环的权值进行加和记录,在最后找到最小树形图之后就不用展开收缩点了  
        }  
        while(j!=i);  
        flag[i] = false; // 环缩成了点i,点i仍然存在  
  
        //收缩点的同时,对边权值进行改变  
        for(int k=1; k<=n; ++k)if(vis[k])  // 在环中点点  
            {  
                for(int j=1; j<=n; j++)if(!vis[j])   // 不在环中的点  
                    {  
                        if(w[i][j] > w[k][j]) w[i][j] = w[k][j];  
                        if(w[j][k]<INF && w[j][k]-w[pre[k]][k] < w[j][i])  
                            w[j][i] = w[j][k] - w[pre[k]][k];  
                    }  
            }  
    }  
    return ans;  
}  

31、优先队列

struct zuobiao
{
    int x,y,output;
    friend bool operator <(zuobiao a,zuobiao b)
    {
        return a.output>b.output;
    }
}now,nex;
    priority_queue<zuobiao>s;
struct cmp{
    bool operator ()(int &a,int &b){
        return a>b;//最小值优先
    }
};       
priority_queue<int,vector<int>,cmp>s;//最小值优先

32、gcd

int gcd(int x,int y)
{
    return y==0?x:gcd(y,x%y);
}
int gcd(int x,int y)
{
    if(x%y==0)return y;
    else return gcd(y,x%y);
}

33、CMN

#define mod 5645618765
const int MAXN = 100; // 组合上限
long long int  c[MAXN][MAXN];    // 组合数
void GetGroup()
{
    c[0][0] = c[1][0] = c[1][1] = 1;
    for (int i=2; i<MAXN; ++i)
    {
        c[i][0] = 1;
        for (int j=1; j<=i; ++j)
            c[i][j] = (c[i-1][j] + c[i-1][j-1])%mod;  // 求模,防止结果过大
    }
    return ;
}
CMN=m!/n!(m-n)!


34、phi函数,欧拉降幂模板

long long eular(long long n) {
    long long ans = n;
    int q = (int)sqrt(n);
    for (int i=2; i<=q; i++) {
        if (n % i == 0) {
            ans -= ans / i;
            while (n % i == 0) {
                n /= i;
            }
        }
    }
    if  (n > 1) {
        ans -= ans / n;
    }

    return ans;
}

35、读入外挂

#include<stdio.h>
#include<string.h>
using namespace std;
int Scan()
{
	int res = 0, ch, flag = 0;

	if((ch = getchar()) == '-')				//判断正负
		flag = 1;

	else if(ch >= '0' && ch <= '9')			//得到完整的数
		res = ch - '0';
	while((ch = getchar()) >= '0' && ch <= '9' )
		res = res * 10 + ch - '0';

	return flag ? -res : res;
}
int main()
{
    int n=Scan();
    printf("%d\n",n);
}

36、大数进制数求余

int judge(date &b)
{
    int tmp=0;
    for(int i=0;i<b.len;i++)
    {
        tmp=(tmp*c+b.a[i])%n;
    }
    return tmp;
}
37、分形

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
using namespace std;
char a[3500][3500];
int vis[7][7];
int n;
char tmp;
void dayin(int cur,int x,int y)
{
    if(cur==1)
    {
        a[x][y]=tmp;
        return ;
    }
    int ss=pow(n,cur-2);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(vis[i][j]==1)
            {
                dayin(cur-1,x+i*ss,y+j*ss);
            }
        }
    }
    return ;
}
int main()
{
    while(~scanf("%d",&n))
    {
        if(n==0)break;
        getchar();
        memset(vis,0,sizeof(vis));
        memset(a,'\0',sizeof(a));
        for(int i=0;i<n;i++)
        {
            gets(a[i]);
            for(int j=0;j<n;j++)
            {
                if(a[i][j]!=' '&&a[i][j]!='\0')
                {
                    vis[i][j]=1;
                    tmp=a[i][j];
                }
            }
        }
        memset(a,' ',sizeof(a));
        int k;
        scanf("%d",&k);
        int s=pow(n,k);//最大范围s、
        dayin(k+1,0,0);
        for(int i=0;i<s;i++)
        {
            a[i][s]='\0';
            puts(a[i]);
        }
    }
}

38、欧拉降幂原因:





















你可能感兴趣的:(个人模板整理)