您的位置:首页 > 其它

模板库

2016-03-12 17:46 218 查看
这里贴出各种算法与数据结构的模板。这篇文章将持续更新。

算法篇

求树的重心

[code]void find(int v,int from,int tot)
{
    sum[v]=1;
    int maxi=0;
    for(int i=last[v];i;i=next[i])
    {
        int u=to[i];
        if(u==from || bz[u]) continue;
        find(u,v,tot);
        sum[v]+=sum[u];
        maxi=max(maxi,sum[u]);
    }
    int t=max(maxi,tot-sum[v]);
    if(t<=val) val=t,root=v;
}


求LCA的倍增算法

[code]int lca(int u,int v)
{
    if(deep[u]<deep[v]) swap(u,v);
    fd(i,int(log2(deep[u])),0)
        if(deep[f[u][i]]>=deep[v]) u=f[u][i];
    fd(i,int(log2(deep[u])),0)
        if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    if(u!=v) return f[u][0];
    return u;
}


求强连通分量or双连通分量的Tarjan算法

[code]void tarjan(int v)
{
    stack[++top]=v;
    low[v]=dfn[v]=++now;
    bz[v]=vis[v]=1;
    for(int i=last[v];i;i=next[i])
    {
        int u=to[i];
        if(dfn[u]==0)
        {
            tarjan(u);
            low[v]=min(low[v],low[u]);
        }
        else
        if(vis[u] && dfn[u]<low[v]) low[v]=dfn[u];
    }
    if(low[v]==dfn[v])
    {
        long long t=0;
        do
        {
            vis[stack[top--]]=0;
            t++;
        }
        while(stack[top+1]!=v);
        ans+=t*(t-1)/2;
    }
}


数论

extended欧几里得算法

[code]void gcd(ll a,ll b,ll &x,ll &y)
{
     if(b==0)
     {
         x=1,y=0;
         return;
     }
     ll xx,yy;
     gcd(b,a%b,xx,yy);
     x=yy,y=xx-a/b*yy;
}


欧拉函数φ\varphi的计算

[code]ll phi(int n)
{
    ll t=n;
    for(int i=2;i*i<=n;i++)
        if(!(n%i))
        {
            t=t/i*(i-1);
            while(!(n%i)) n/=i;
        }
    if(n>1) t=t/n*(n-1);
    return num;
}


线性筛法

[code]void pre(int n)
{

    mu[1]=1;
    fo(i,2,n)
    {
        if(!bz[i])
        {
            mu[i]=-1;
            pri[++pri[0]]=i;
        }
        fo(j,1,pri[0])
        {
            int t=i*pri[j];
            if(t>n) break;
            bz[t]=1;
            if(i%pri[j]==0)
            {
                mu[t]=0;
                break;
            }
            mu[t]=-mu[i];
        }
    }
}


字符串

SA的倍增构造

[code]void DA()
{
    int mx=0;
    fo(i,1,n) mx=max(mx,wv[i]=x[i]=s[i]-'a'+1);
    fill(ws,ws+mx+1,0);
    fo(i,1,n) ws[wv[i]]++;
    fo(i,1,mx) ws[i]+=ws[i-1];
    fd(i,n,1) SA[ws[wv[i]]--]=i;
    for(int len=1;len<=n;len*=2)
    {
        int m=0;
        fo(i,n-len+1,n) y[++m]=i;
        fo(i,1,n)
            if(SA[i]>len) y[++m]=SA[i]-len;
        mx=0;
        fo(i,1,n) mx=max(mx,wv[i]=x[y[i]]);
        fill(ws,ws+mx+1,0);
        fo(i,1,n) ws[wv[i]]++;
        fo(i,1,mx) ws[i]+=ws[i-1];
        fd(i,n,1) SA[ws[wv[i]]--]=y[i];
        fo(i,1,n) y[i]=x[i],x[i]=0;
        x[SA[m=1]]=1;
        fo(i,2,n) x[SA[i]]=cmp(SA[i-1],SA[i],len)?m:++m;
        if(m==n) break;
    }
    fo(i,1,n) rank[SA[i]]=i;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: