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

  • 相关阅读:
    Atitit attilax要工作研究的要素 纪要 方案 趋势 方向 概念 理论
    Atitit 常见每日流程日程日常工作.docx v7 r8f
    Atitit it 互联网 软件牛人的博客列表
    Atitit 信息链(Information Chain)的概念理解 attilax总结
    Atitit 知识点的体系化 框架与方法 如何了解 看待xxx
    Atitit 聚合搜索多个微博 attilax总结
    Atitit 企业知识管理PKM与PIM
    Atitit 项目沟通管理 Atitit 沟通之道 attilax著.docx
    Atitit 项目管理软件 在线服务 attilax总结 1. 项目管理协作的历史 1 1.1. Worktile 406k 1 1.2. Teambition  584k in baidu
    Atitit.每周末总结 于每周一计划日程表 流程表 v8 import 上周遗漏日志补充 检查话费 检查流量情况 Crm问候 Crm表total and 问候
  • 原文地址:https://www.cnblogs.com/oierjzy/p/11318013.html
Copyright © 2011-2022 走看看