zoukankan      html  css  js  c++  java
  • 代码模板库

    图论

    tarjan+缩点:

    //有向图tarjan缩点
    void add(int a,int b)
    {
        bian[++ecnt].to=b;
        bian[ecnt].nxt=head[a];
        head[a]=ecnt;
    }
    void add1(int a,int b)//函数名称容易出锅,以后要用有区分度的名称
    {
        tu[++rcnt].to=b;
        tu[rcnt].nxt=headtu[a];
        headtu[a]=rcnt;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tim;//
        stk[++tk]=u;//入栈
        vis[u]=true;//入栈标记
        for(int i=head[u];i;i=bian[i].nxt)
        {
            int v=bian[i].to;
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[v],low[u]);
            }
            else if(vis[v])//注意这附近的if else 括号匹配,多次出锅
                low[u]=min(low[v],low[u]);
        }
        if(dfn[u]==low[u])
        {
            num++;
            while(stk[tk]!=u)
            {
                vis[stk[tk]]=false;
                shuyu[stk[tk]]=num;
                stk[tk]=0;
                tk--;
            }//可以用do while代替,用while的话执行完要再来一次
            vis[stk[tk]]=false;
            shuyu[stk[tk]]=num;//记录属于哪个联通块
            stk[tk]=0;//出栈
            tk--;
        }
    }
    void suo()//枚举点和边,原来的边左右两点如果不在同一联通块,则建新边
    {
        for(int i=1;i<=n;i++)
        {
            int u=shuyu[i];
            shd[u]+=dian[i];
            for(int j=head[i];j;j=bian[j].nxt)
            {
                int v=bian[j].to;
                if(shuyu[v]!=u)
                {
                    add1(u,shuyu[v]);
                }
            }
        }
    }
    int main()
    {
        n=read();m=read();
        int a,b;
        for(int i=1;i<=n;i++)
            dian[i]=read();
        for(int i=1;i<=m;i++)
        {
            a=read();b=read();
            add(a,b);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])//注意这里,整个图不一定是连通图,所以要遍历整个图
                tarjan(i);
        }
        suo();//缩点
        for(int i=1;i<=num;i++)
            ans=max(ans,dfs(i));
        cout<<ans;
        return 0;
    }
    View Code

    tarjan求点双:

    void tarjan(int x)
    {
        dfn[x]=low[x]=++tim;
        int flag=0;
        for(int i=head[x];i;i=bian[i].nxt)
        {
            int y=bian[i].to;
            if(!dfn[y])
            {
                tarjan(y);
                low[x]=min(low[x],low[y]);
                if(low[y]>=dfn[x])
                {
                    flag++;
                    if((x!=rof||flag>1)&&gee[x]==0)
                        ge[++cnt]=x,gee[x]=1;//you chong fu
                }
            }
            else low[x]=min(low[x],dfn[y]);
        }
    }
    
    ~int main
    for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
                rof=i,tarjan(i);
        }
    View Code

    tarjan求边双:

    void tarjan(int u,int bian)
    {
        dfn[u]=low[u]=++tim;
        for(int i=head[u];i;i=bian[i].nxt)
        {
            int v=bian[i].to;
            if(!dfn[v])
            {
                tarjan(v,i);
                low[u]=min(low[u],low[v]);
                if(low[v]>dfn[u])
                    isbridge[i]=isbridge[i^1]=1;
            }
            else if(i!=(bian^1))
                low[u]=min(low[u],dfn[v]);
        }
    } 
    ~int main
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i,0); 
    View Code

    最小生成树(prim):

    //prim
    void prim()
    {
        memset(dis,0x3f,sizeof dis);
        dis[1]=0;
        int b=1;
        for(int j=1;j<=n;j++)
        {
            vis[b]=true;cnt++;ans+=dis[b];
            for(int i=head[b];i;i=bian[i].nxt)
            {
                int c=bian[i].to;
                int d=bian[i].quan;
                if(d<dis[c])dis[c]=d;
            }
            mx=0x3f3f3f3f;
            for(int i=1;i<=n;i++)
            {
                if(dis[i]<mx&&vis[i]==false)
                {
                    mx=dis[i];
                    b=i;
                }
            }
        }
    }
    View Code

     最短路(dijstra):

    void dij()
    {
        memset(dis,0x3f,sizeof(dis));
        int qi=s;
        dis[qi]=0;
        q.push(bbb{qi,0});
        while(!q.empty())
        {
            bbb w=q.top();
            int k=w.jiedian;
            q.pop();
            if(!vis[k])
            {
                vis[k]=true;
                for(int i=head[k];i;i=bian[i].nxt)
                {
                    int v=bian[i].to;
                    if(dis[v]>dis[k]+bian[i].leng)
                    {
                        dis[v]=dis[k]+bian[i].leng;
                        q.push(bbb{v,dis[v]});
                    }
                }
            }
        }
    }
    View Code

    最短路(SPFA):(忘了急需复习

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,s;
    int a,b,c;
    int dis[100005];
    bool vis[100005];
    int head[100005],ecnt;
    struct aaa
    {
        int jiedian,dis;
    };
    bool operator <(const aaa& a,const aaa& b){
        return a.dis>b.dis;
    }
    priority_queue<aaa>q;
    struct edge{
        int to,nxt,dis;
    }ed[200010];
    void addedge(int f,int to,int dis)
    {
        ed[++ecnt].to=to;
        ed[ecnt].dis=dis;
        ed[ecnt].nxt=head[f];
        head[f]=ecnt;
    }
    inline int read()
    {
        int x=0;
        char c=getchar();
        bool flag=0;
        while(c<'0'||c>'9'){if(c=='-')flag=1;   c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return flag?-x:x;
    }
    void suanfa()
    {
        memset(dis,0x3f,sizeof dis);
        int k=s;
        dis[s]=0;
        for(int i=head[k];i!=0;i=ed[i].nxt)
                {
                    int v=ed[i].to;//ed xianduan
                    if(dis[v]>dis[k]+ed[i].dis)
                    {
                        q.push(aaa{ed[i].to,dis[k]+ed[i].dis});
                        dis[v]=dis[k]+ed[i].dis;
                    }
                        
                }
        while(!q.empty())
        {
            aaa w=q.top();
            int k=w.jiedian;
            q.pop();
            if(vis[k]==false)
            {
                vis[k]=true;//mark white;
                for(int i=head[k];i!=0;i=ed[i].nxt)
                {
                    int v=ed[i].to;//ed xianduan
                    if(dis[v]>dis[k]+ed[i].dis)
                    {
                        q.push(aaa{ed[i].to,dis[k]+ed[i].dis});
                        dis[v]=dis[k]+ed[i].dis;
                    }
                }
            }
        }
    }
    int main()
    {
        n=read();m=read();s=read();
        for(int i=1;i<=m;i++)
        {
            a=read();b=read();c=read();
            addedge(a,b,c);
        }
        suanfa();
        for(int i=1;i<=n;i++)
        {
            if(dis[i]!=0x3f3f3f3f)
                printf("%d ",dis[i]);
            else cout<<2147483647<<" ";
        }
        return 0;
    }
    View Code 

    倍增lca:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,s;
    int a,b;
    struct aaa
    {
        int to,nxt;
    }bian[1000001];
    int head[500001];
    int ecnt;
    int deep[500001];
    bool vis[500001];
    int dian[500001][20];
    int deepmax;
    
    inline int read()
    {
        int x=0;
        char c=getchar();
        bool flag=0;
        while(c<'0'||c>'9'){if(c=='-')flag=1;   c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return flag?-x:x;
    }
    
    void dfs(int a)
    {
        for(int i=head[a];i;i=bian[i].nxt)
        {
            int b=bian[i].to;
            if(!deep[b])
            {
                deep[b]=deep[a]+1;
                dian[b][0]=a;
                dfs(b);
            }
        }
    }
    
    void st()
    {
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i<=n;i++)
                {
                    if(dian[i][j-1]) dian[i][j]=dian[dian[i][j-1]][j-1];
                }
    }
    
    void add(int a,int b)
    {
        bian[++ecnt].to=b;
        bian[ecnt].nxt=head[a];
        head[a]=ecnt;
        bian[++ecnt].to=a;
        bian[ecnt].nxt=head[b];
        head[b]=ecnt;
    }
    
    int lca(int a,int b)
    {
        if(deep[a]<deep[b])swap(a,b);
        int i;
        for(i=0;(1<<i)<=deep[a];i++);
        i--;
        for(int j=i;j>=0;j--)
        {
            if(deep[a]-(1<<j)>=deep[b])
            {
                a=dian[a][j];
            }
        }
        if(a==b)return a;
        for(int j=i;j>=0;j--)
        {
            if(dian[a][j]!=0&&dian[a][j]!=dian[b][j])
            {
                a=dian[a][j];
                b=dian[b][j];
            }
        }
        return dian[a][0];
    }
    
    int main()
    {
        n=read();m=read();s=read();
        for(int i=1;i<=n-1;i++)
        {
            a=read();b=read();
            add(a,b);
        }
        dian[s][0]=0;
        deep[s]=1;//初始化深度; 
        dfs(s);//求深度;
        st();
        for(int i=1;i<=m;i++)
        {
            a=read();b=read();
            int c=lca(a,b);
        //    if(a==s||b==s)cout<<s<<endl;
        //    else
            printf("%d
    ",c);
        }
        return 0;
    }
    View Code

    数学

     线性筛:

    //线性筛
    bool sushu[10000005];
    int n,m;
    int sushubiao[5000005];
    int q;
    void shai()
    {
        for(int i=2;i<=n;i++)
        {
            if(!sushu[i])
                sushubiao[++q]=i;
            for(int j=1;j<=q&&sushubiao[j]*i<=n;j++)
            {
                sushu[sushubiao[j]*i]=true;
                if(i%sushubiao[j]==0)break;
            }
        }
    }
    View Code

    乘法逆元:

    void ny()
    {
        inv[1]=1;
        for(int i=2;i<=n;i++)
            inv[i]=1ll*(p-(p/i))*inv[p%i]%p;
    }
    a^p-2===a^-1 (mod p)
    View Code

    高斯消元:

    #include<bits/stdc++.h>
    using namespace std;
    const double jd=5e-3;
    int n;
    double fc[55][55];
    double xi[55];
    double jie[55];
    inline int read()
    {
        int x=0;bool f=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return f?-x:x;
    }
    void Gauss()
    {
        for(int i=1;i<=n-1;i++)//消第i个未知数; 
        {
            for(int j=i+1;j<=n;j++)
            {
                if(fc[i][i]==0)
                {
                    for(int k=1;k<=n;k++)
                    {
                        swap(fc[i][k],fc[j][k]);
                    }
                    swap(xi[i],xi[j]);
                }
                if(abs(fc[j][i])<jd)
                    continue;
                double cun=fc[i][i]/fc[j][i];
                for(int k=i;k<=n;k++)
                    fc[j][k]=fc[j][k]*cun-fc[i][k];
                xi[j]=xi[j]*cun-xi[i];
            }
        }
    }
    int jfc()
    {
        for(int i=n;i>=1;i--)
        {
            double zuo=0,you=xi[i];
            for(int j=n;j>i;j--)
                zuo+=fc[i][j]*jie[j];
            you-=zuo;
            if(abs(fc[i][i])<jd&&abs(you)>jd)return -1;
            if(abs(fc[i][i])<jd&&abs(you)<jd)return 0;
            jie[i]=you/fc[i][i];
        }
        return 1;
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                fc[i][j]=read()*1.0;
            xi[i]=read()*1.0;
        }
        Gauss();
        switch(jfc())
        {
            case 1:
            {
                for(int i=1;i<=n;i++)
                {
                    if(abs(jie[i])<jd)printf("x%d=0
    ",i);
                    else printf("x%d=%.2lf
    ",i,jie[i]);
                }
                    
                break;
            }
            case 0://无穷多解
            {
                cout<<0<<endl;
                break;
            }
            case -1://无解
            {
                cout<<-1<<endl;
                break;
            }
        }
    }
    View Code

    exgcd:

    void exgcd(ll a,ll b)
    {
        if(b==0)
        {
            x=1;y=0;
            return;
        }
        exgcd(b,a%b);
        ll tem=x;
        x=y;
        y=tem-a/b*y;
    }
    View Code

    扩展中国剩余定理(excrt):

    #include<bits/stdc++.h>
    using namespace std;
    #define ll __int128
    ll ans,x,y,a,b,c,yu[100005],mo[100005],M,n;
    long long read()
    {
        ll f=1,x=0;
        char ss=getchar();
        while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
        while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
        return f*x;
    }
    long long gcd(ll a,ll b)
    {
        ll c;
        while(a%b)
        {
            c=a%b;
            a=b;
            b=c;
        }
        return b;
    }
    long long lcm(ll a,ll b)
    {
        return a/gcd(a,b)*b;
    }
    void exgcd(ll a,ll b)
    {
        if(b==0)
        {
            x=1;y=0;
            return;
        }
        exgcd(b,a%b);
        ll tem=x;
        x=y;
        y=tem-a/b*y;
    }
    long long excrt()
    {
        M=mo[1];ans=yu[1];
        for(int i=2;i<=n;i++)
        {
            exgcd(M,mo[i]);
            ll gcdd=gcd(M,mo[i]);
            if((yu[i]-ans)%gcdd!=0)return -1;
            x*=(yu[i]-ans)/gcdd;
            ans=ans+x*M;
            M=M/gcd(M,mo[i])*mo[i];
            ans=(ans%M+M)%M;
        }
        return ans;
    }
    int main()
    {
        n=read();
        for(ll i=1;i<=n;i++)
            mo[i]=read(),yu[i]=read();
        cout<<excrt();
        return 0;
    }
    View Code

    卢卡斯定理:(小模数的组合数)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int T;
    ll n,m,p;
    ll a[100005];
    inline ll read()
    {
        bool f=0;ll x=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return f?-x:x;
    }
    ll ks(ll x,ll k)
    {
        ll num=1;
        while(k)
        {
            if(k&1)
                num=num*x%p;
            x=x*x%p;
            k>>=1;
        }
        return num;
    }
    ll c(ll n,ll m)
    {
        if(m>n)return 0;
        return ((a[n]*ks(a[m],p-2))%p*ks(a[n-m],p-2)%p);
    }
    ll lucas(ll n,ll m)
    {
        if(!m)return 1;
        return c(n%p,m%p)*lucas(n/p,m/p)%p;
    }
    int main()
    {
        T=read();
        while(T--)
        {
            n=read();m=read();p=read();
            a[0]=1;
            for(int i=1;i<=p;i++)a[i]=(a[i-1]*i)%p;
            cout<<lucas(n+m,n)<<endl;
        }
        return 0;
    }
    View Code

    数据结构

    树状数组

    //树状数组
    int lowb(int x){return x&-x;}
    void add(int x,int k)
    {
        for(;x<=n;x+=lowb(x))
            s[x]+=k;
    }
    long long ask(int a)
    {
        long long ans=0;
        while(a!=0)
        {
            ans+=s[a];
            a-=lowb(a); 
        }
        return ans;
    }
    //询问l~r: ans=ask(r)-ask(l-1)
    View Code

    线段树

    //这是线段树1,如果有乘法,先乘后加即可。
    //还有一些线段树的题,是线段树结构和标记的巧妙应用
    #include<bits/stdc++.h>
    using namespace std;
    const int N=100005;
    int n,m;
    int a[N];
    struct aaa
    {
        int l,r;
        long long sum,lazy;
    }t[4*N];
    inline int read()
    {
        int x=0;bool flag=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=true;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return flag?-x:x;
    }
    void build(int num,int l,int r)
    {
        t[num].l=l;t[num].r=r;
        if(l==r)
        {
            t[num].sum=a[l];
            return;
        }
        int mid=(l+r)/2;
        build(num*2,l,mid);
        build(num*2+1,mid+1,r);
        t[num].sum=t[num*2].sum+t[num*2+1].sum;
    }
    void push(int num)
    {
        t[2*num+1].sum+=t[num].lazy*(t[2*num+1].r-t[2*num+1].l+1);
        t[2*num+1].lazy+=t[num].lazy;
        t[2*num].sum+=t[num].lazy*(t[2*num].r-t[2*num].l+1);
        t[2*num].lazy+=t[num].lazy;
        t[num].lazy=0;
    }
    void add(int l,int r,int zhi,int num)
    {
        int x=t[num].l,y=t[num].r;
        if(x==l&&y==r)
        {
            t[num].lazy+=zhi;
            t[num].sum+=(r-l+1)*zhi;
            return;
        }    
        int mid=(x+y)/2;
        push(num);
        if(r<=mid)
            add(l,r,zhi,2*num);
        else if(l>mid)
            add(l,r,zhi,2*num+1);
        else
        {
            add(l,mid,zhi,2*num);
            add(mid+1,r,zhi,2*num+1);
        }
        t[num].sum=t[2*num].sum+t[2*num+1].sum;
    }
    long long ask(int l,int r,int num)
    {
        int x=t[num].l,y=t[num].r;
        if(x==l&&y==r)return t[num].sum;
        int mid=(x+y)/2;
        if(t[num].lazy)push(num);
        if(r<=mid)
            return ask(l,r,2*num);
        else if(l>mid)
            return ask(l,r,2*num+1);
        else return ask(l,mid,2*num)+ask(mid+1,r,2*num+1);    
    }
    int main()
    {
        n=read();m=read();
        int e,b,c,d;
        for(int i=1;i<=n;i++)
            a[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            e=read();
            if(e==1)
            {
                b=read();c=read();d=read();
                add(b,c,d,1);
            }
            else if(e==2)
            {
                b=read();c=read();
                long long ans=ask(b,c,1);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    View Code

    其他 

    st表:不修改的区间内求最大最小值(无法求和)

    //st表模板
    //不修改的区间求最大最小值,无法求和
    //st[i][j]表示从i开始(包括i),之后2^j的区间内的最大/最小值
     for(int i=1;i<=n;i++)//对于自身的预处理
            mx[i][0]=a[i];
        for(int j=1;(1<<j)<=n;j++)//先循环2的j次方,否则信息不全无法合并。
            for(int i=1;i+(1<<j)-1<=n;i++)//i+(1<<j)-1<=n,注意要减1,(想意思)
            {
                mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
            }
        for(int i=1;i<=m;i++)//查询
        {
            b=read();c=read();
            k=log2(c-b+1);//查询是2的几次方
            ans=max(mx[b][k],mx[c-(1<<k)+1][k]));//由于k是向下取整,所以要这样做避免少算。    
        }
    View Code

     快速幂:

    ll ksm(ll x,ll k)
    {
        ll num=1;
        while(k)
        {
            if(k&1)
                num=num*x%p;
            x=x*x%p;
            k>>=1;
        }
        return num%p;
    }
    View Code

    三分:

    //如果是整数定义域,边界很难处理
    while(r-l>=mn)
        {
            double a=(2*l+r)/3,b=(l+2*r)/3;
            if(f(a)>f(b))
                r=b;
            else l=a;
        }
    View Code

    哈希:

    for(int i=1;i<=n;i++)
        {
            scanf("%s",a[i]+1);
            int q=strlen(a[i]+1);
            for(int j=1;j<=q;j++)    
                hsh[i]=(hsh[i]*139+a[i][j])%100000007;    
        }
    View Code

    a

  • 相关阅读:
    Linux 内核 MCA 总线
    Linux 内核PC/104 和 PC/104+
    Linux 内核即插即用规范
    Linux 内核硬件资源
    Linux 内核 回顾: ISA
    Linux 内核硬件抽象
    Linux 内核硬件抽象
    Linux 内核PCI 中断
    Linux 内核存取 I/O 和内存空间
    哥们的面试经历
  • 原文地址:https://www.cnblogs.com/oierjzy/p/11318013.html
Copyright © 2011-2022 走看看