NOIP模板整理

来源:互联网 发布:ubuntu安装qt5 编辑:程序博客网 时间:2024/05/01 19:02

2016NOIP RP++
持续更新中……

图论:

1.最短路:

floyd
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=1005;int d[maxn][maxn];int n,m,s,e;void floyd(){    for(int k=1;k<=n;k++)         for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                if(i!=j&&i!=k&&k!=j)                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);   }int main(){    scanf("%d%d%d%d",&n,&m,&s,&e);    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            d[i][j]=1e9;    for(int i=1;i<=m;i++)    {        int f,t,c;        scanf("%d%d%d",&f,&t,&c);        d[f][t]=c;        d[t][f]=c;    }    floyd();    printf("%d\n",d[s][e]);    return 0;       }       
Ⅱspfa
①普通:
#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;const int maxn=100005;struct dqs{    int f,t,c;}hh[maxn];int tot=0,first[maxn],next[maxn],d[maxn];bool used[maxn];void build(int f,int t,int c){    hh[++tot]=(dqs){f,t,c};    next[tot]=first[f];    first[f]=tot;}queue<int>q;int n,m,s,e;void spfa(int s){    d[s]=0;    q.push(s);    used[s]=1;    while(!q.empty())    {        int x=q.front();        q.pop();        used[x]=0;        for(int i=first[x];i;i=next[i])        {            int u=hh[i].t;            if(d[u]>d[x]+hh[i].c)            {                d[u]=d[x]+hh[i].c;                if(!used[u])                {                    q.push(u);                    used[u]=1;                }            }        }    }}int main(){    scanf("%d%d%d%d",&n,&m,&s,&e);    for(int i=1;i<=n;i++)        d[i]=1e9;    for(int i=1;i<=m;i++)    {        int f,t,c;        scanf("%d%d%d",&f,&t,&c);        build(f,t,c);        build(t,f,c);    }    spfa(s);    printf("%d\n",d[e]);    return 0;}
②spfa(slf优化)
deque<int>q;void spfa(int s){    for(int i=1;i<=n;i++)        d[i]=1e9;    d[s]=0;    q.push_back(s);    used[s]=1;    while(!q.empty())    {        int x=q.front();        q.pop_front();        used[x]=0;        for(int i=first[x];i;i=next[i])        {            int u=hh[i].t;            if(d[u]>d[x]+hh[i].c)            {                d[u]=d[x]+hh[i].c;                if(!used[u])                {                    used[u]=1;                    if(!q.empty())                    {                        if(d[u]<d[q.front()])                            q.push_front(u);                        else                            q.push_back(u);                    }                    else                        q.push_back(u);                }            }        }    }}   
③spfa判负环
int tim[maxn];bool spfa(int s){    d[s]=0;    q.push(s);    used[s]=1;    while(!q.empty())    {        int x=q.front();        q.pop();        used[x]=0;        for(int i=first[x];i;i=next[i])        {            int u=hh[i].t;            if(d[u]>d[x]+hh[i].c)            {                d[u]=d[x]+hh[i].c;                if(!used[u])                {                    if(++tim[u]>n)                        return false;                    q.push(u);                    used[u]=1;                }            }        }    }    return true;}
ⅢDijkstra算法
①普通
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=100005;struct dqs{    int f,t,c;}hh[maxn];int tot=0,first[maxn],next[maxn],d[maxn];bool used[maxn];void build(int f,int t,int c){    hh[++tot]=(dqs){f,t,c};    next[tot]=first[f];    first[f]=tot;}int n,m,s,e;void Dijkstra(){    for(int i=1;i<=n;i++)        d[i]=1e9;     d[s]=0;    while(true)    {        int x=-1;        for(int i=1;i<=n;i++)        {            if(!used[i])                if(x==-1||d[i]<d[x])                    x=i;                            if(x==-1) break;            used[x]=1;            for(int i=first[x];i;i=next[i])            {                int u=hh[i].t;                if(d[u]>d[x]+hh[i].c)                    d[u]=d[x]+hh[i].c;            }        }    }}int main(){    scanf("%d%d%d%d",&n,&m,&s,&e);    ......}
②堆优化
#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;const int maxn=200005;struct dqs{    int f,t,c;}hh[maxn];struct dqm{    int num,dis;};bool operator <(dqm a,dqm b){    return a.dis>b.dis;}int tot=0,first[maxn],next[maxn],d[maxn];bool used[maxn];void build(int f,int t,int c){    hh[++tot]=(dqs){f,t,c};    next[tot]=first[f];    first[f]=tot;}priority_queue<dqm>q;void dij(int s){    d[s]=0;    q.push({s,d[s]});    while(!q.empty())    {        int head = q.top().num;        q.pop();        used[head]=1;        for(int i=first[head];i;i=next[i])        {            int u=hh[i].t;            if(d[u]>d[head]+hh[i].c)            {                d[u]=d[head]+hh[i].c;                if(!used[u])                    q.push((dqm){u,d[u]});            }        }    }}int main(){    int n,m,s,e;    scanf("%d%d%d%d",&n,&m,&s,&e);    ......}

2.最小生成树

①kruskal:

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int maxn=200005;struct dqs{    int f,t,c;}hh[maxn];int fa[maxn];bool cmp(dqs a,dqs b){    return a.c<b.c;}int find(int x){    if(fa[x]==x)        return x;    else        return fa[x]=find(fa[x]);}int main(){    int n,m,tot=0,ans=0;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        fa[i]=i;    for(int i=1;i<=m;i++)    {        int f,t,c;        scanf("%d%d%d",&f,&t,&c);        hh[++tot]=(dqs){f,t,c};    }    sort(hh+1,hh+tot+1,cmp);    for(int i=1;i<=tot;i++)    {        int x=find(hh[i].f);        int y=find(hh[i].t);        if(x!=y)        {            fa[x]=y;            ans+=hh[i].c;        }    }    printf("%d\n",ans);    return 0;}

3. LCA

模板:小机房的树

①暴力
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=100005;struct dqs{    int f,t,c;}hh[maxn];int deep[maxn],d[maxn],fa[maxn]; int tot=0,first[maxn],next[maxn];void build(int f,int t,int c){    hh[++tot]=(dqs){f,t,c};    next[tot]=first[f];    first[f]=tot;}void dfs(int x,int sd){    deep[x]=sd;    for(int i=first[x];i;i=next[i])    {        int u=hh[i].t;        if(deep[u])            continue;        else        {            fa[u]=x;            d[u]=d[x]+hh[i].c;            dfs(u,sd+1);        }    }}int lca(int x,int y){    if(deep[x]<deep[y])    swap(x,y);    while(deep[x]>deep[y])    {        x=fa[x];    }    while(x!=y)    {        x=fa[x];        y=fa[y];    }    return x;}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n-1;i++)    {        int f,t,c;        scanf("%d%d%d",&f,&t,&c);        build(f,t,c);        build(t,f,c);    }    dfs(1,0);    int m;    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        int u,v;        scanf("%d%d",&u,&v);        int xx=lca(u,v);        printf("%d\n",d[u]+d[v]-2*d[xx]);    }}
②倍增
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn=250010;struct dqs{    int f,t,c;}hh[maxn<<1];int tot=0,fa[maxn][31],next[maxn],first[maxn],f[maxn],d[maxn];void build(int ff,int tt,int cc){    hh[++tot]=(dqs){ff,tt,cc};    next[tot]=first[ff];    first[ff]=tot;}int deep[maxn];void dfs(int x,int sd){    deep[x]=sd;    int u;    for(int i=first[x];i;i=next[i])    {        u=hh[i].t;        if(!deep[u]&&u)        {            f[u]=x;            d[u]=d[x]+hh[i].c;            dfs(u,sd+1);        }    }}int lca(int x,int y){    if(deep[x]<deep[y])    swap(x,y);    int deepcha=deep[x]-deep[y];    for(int i=0;i<=30;i++)    {        if(1<<i&deepcha)        x=fa[x][i];    }    for(int i=30;i>=0;i--)    {        if(fa[x][i]!=fa[y][i])        {            x=fa[x][i];            y=fa[y][i];        }    }    if(x!=y)        return f[x];    return x;}int main(){    int n;    scanf("%d",&n);    int u,v,c;    for(int i=1;i<n;i++)    {        scanf("%d%d%d",&u,&v,&c);        build(u,v,c);        build(v,u,c);    }    dfs(0,0);    for(int i=0;i<n;i++)        fa[i][0]=f[i];    for(int j=1;j<=20;j++)    for(int i=1;i<=n;i++)        fa[i][j]=fa[fa[i][j-1]][j-1];    int m;    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        scanf("%d%d",&u,&v);        int xx=lca(u,v);        printf("%d\n",d[u]+d[v]-2*d[xx]);    }    return 0;}

4. 拓扑排序

模板:poj2367

#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;const int maxn=200005;struct dqs{    int f,t,c;}hh[maxn];int tot=0,first[maxn],next[maxn],du[maxn];void build(int f,int t){    hh[++tot]=(dqs){f,t};    next[tot]=first[f];    first[f]=tot;}queue<int>q;void tp(){    while(!q.empty())    {        int x=q.front();        q.pop();        printf("%d ",x);        for(int i=first[x];i;i=next[i])        {            int u=hh[i].t;            du[u]--;            if(!du[u])            q.push(u);        }    }}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        int x;        while(true)        {            scanf("%d",&x);            if(x==0)            break;            build(i,x);            du[x]++;        }    }    for(int i=1;i<=n;i++)        if(!du[i])            q.push(i);    tp();    return 0;}

5. Tarjan(无向图求环)

强连通分量:

模板:codevs2822爱在心中

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=10005;struct dqs{    int f,t;}hh[maxn];int tot=0;int first[maxn],next[maxn];void build(int f,int t){    hh[++tot]=(dqs){f,t};    next[tot]=first[f];    first[f]=tot;}int dfn[maxn],low[maxn],stack[maxn],size[maxn],du[maxn],jlqlt[maxn];bool in_stack[maxn];int tot1=0,cnt=0,snum=0;void group(int x){    dfn[x]=low[x]=++tot1;    stack[++snum]=x;    in_stack[x]=1;    for(int i=first[x];i;i=next[i])    {        int u=hh[i].t;        if(!dfn[u])        {            group(u);            low[x]=min(low[x],low[u]);        }        else if(in_stack[u])            low[x]=min(low[x],dfn[u]);    }    if(dfn[x]==low[x])    {        cnt++;        while(true)        {            jlqlt[stack[snum]]=cnt;            in_stack[stack[snum]]=0;            size[cnt]++;            snum--;            if(stack[snum+1]==x)                break;        }    }}int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int a,b;        scanf("%d%d",&a,&b);        build(a,b);    }    for(int i=1;i<=n;i++)        if(!dfn[i])            group(i);    for(int i=1;i<=n;i++)        for(int j=first[i];j;j=next[j])        {            int u=hh[j].t;            if(jlqlt[i]!=jlqlt[u])                du[jlqlt[i]]++;        }    int sum1=0,sum2=0,x;    for(int i=1;i<=cnt;i++)    {        if(size[i]>1)            sum1++;        if(!du[i])        {            sum2++;            x=i;                }    }    printf("%d\n",sum1);    if(sum2==1&&size[x]!=1)    {        for(int i=1;i<=n;i++)        {            if(jlqlt[i]==x)            printf("%d ",i);        }    }    else    printf("-1\n");    return 0;} 

数据结构

1.线段树

模板:区间修改,区间查询

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;typedef long long ll;const int maxn=200005;struct dqs{    int l,r;    ll add;    ll sum;}hh[maxn<<2];int xl[maxn];void build(int p,int l,int r){    hh[p].l=l;    hh[p].r=r;    if(l==r)    {        hh[p].sum=xl[l];        return;    }    int mid=(l+r)>>1;    build(p*2,l,mid);    build(p*2+1,mid+1,r);    hh[p].sum=hh[p*2].sum+hh[p*2+1].sum;}void spread(int p){    if(hh[p].add)    {        hh[p*2].sum+=(ll)(hh[p*2].r-hh[p*2].l+1)*(ll)hh[p].add;        hh[p*2+1].sum+=(ll)(hh[p*2+1].r-hh[p*2+1].l+1)*(ll)hh[p].add;        hh[p*2].add+=hh[p].add;        hh[p*2+1].add+=hh[p].add;        hh[p].add=0;    }}void change(int p,int l,int r,ll x){    if(hh[p].l>=l&&hh[p].r<=r)    {        hh[p].sum+=(long long)(hh[p].r-hh[p].l+1)*x;        hh[p].add+=x;        return;    }    spread(p);    int mid=(hh[p].l+hh[p].r)>>1;    if(l<=mid)    change(p*2,l,r,x);    if(mid<r)    change(p*2+1,l,r,x);    hh[p].sum = hh[p*2].sum+hh[p*2+1].sum;}ll ask(int p,int l,int r){    if(l<=hh[p].l&&hh[p].r<=r)        return hh[p].sum;    spread(p);    ll ans = 0;    int mid=(hh[p].l+hh[p].r)>>1;    if(l<=mid)    ans += ask(p*2,l,r);    if(mid<r)    ans += ask(p*2+1,l,r);    return ans;}int main(){    int n,q;    scanf("%d",&n);     for(int i=1;i<=n;i++)    scanf("%d",&xl[i]);    build(1,1,n);    scanf("%d",&q);    for(int i=1;i<=q;i++)    {        int read;        scanf("%d",&read);        if(read==1)        {            int a,b;             ll c;            scanf("%d%d%lld",&a,&b,&c);            change(1,a,b,c);        }        if(read==2)        {            int a,b;            scanf("%d%d",&a,&b);            printf("%lld\n",ask(1,a,b));        }    }    return 0;}

2.排序

Ⅰ归并排序
#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=200005; long long tmp[maxn],a[maxn];long long ans=0;void merge(int l,int mid,int r){    int i=l,j=mid+1,k=l;    while(i<=mid&&j<=r)    {        if(a[i]>a[j])        {            tmp[k++]=a[j++];            ans+=mid+1-i;        }        else            tmp[k++]=a[i++];     }    while(i<=mid)        tmp[k++]=a[i++];    while(j<=r)        tmp[k++]=a[j++];    for(int i=l;i<=r;i++)        a[i]=tmp[i];}void merge_sort(int l,int r){    if(l<r)    {        int mid=(l+r)>>1;        merge_sort(l,mid);        merge_sort(mid+1,r);        merge(l,mid,r);    } }int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%lld",&a[i]);    merge_sort(1,n);    for(int i=1;i<=n;i++)        cout<<a[i]<<" ";    cout<<endl;    printf("%lld",ans);}
Ⅱ堆排序(小根)

①手打堆排序

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int maxn=200005;int heap[maxn],cnt=0;void push(int x){    cnt++;    int now=cnt;    heap[now]=x;    while(now>1)    {        if(heap[now]<heap[now/2])        {            swap(heap[now],heap[now/2]);            now/=2;        }        else break;    }}void pop(){    heap[1]=heap[cnt];    int now=1;    while(now*2+1<=cnt)    {        int l=now*2,r=now*2+1;        if(heap[l]<heap[now])        {            if(heap[r]<heap[l])                swap(l,r);            swap(heap[l],heap[now]);            now=l;        }        else if(heap[r]<heap[now])        {            swap(heap[r],heap[now]);            now=r;        }        else break;    }    cnt--;}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        int x;        scanf("%d",&x);        push(x);    }    for(int i=1;i<=n;i++)    {        printf("%d ",heap[1]);        pop();    }}

②STL实现

#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;const int maxn=200005;struct dqs{    int num;};bool operator<(dqs a,dqs b){    return a.num>b.num;}priority_queue<dqs>q;int main(){    int n;    dqs x;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%d",&x.num);        q.push(x);    }    while(!q.empty())    {        printf("%d ",q.top());        q.pop();    }    return 0;} 

数论

1.筛法

Ⅰ线性筛
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring> using namespace std;const int maxn=200005;int prime[maxn];bool not_prime[maxn];int main(){    int n,cnt=0;    scanf("%d",&n);    memset(not_prime,0,sizeof(not_prime));    not_prime[1]=true;    for(int i=2;i<=n;i++)    {        if(!not_prime[i])            prime[++cnt]=i;        for(int j=1;j<=cnt;j++)        {            if(prime[j]*i>n)    break;            not_prime[prime[j]*i]=true;            if(i%prime[j]==0) break;        }    }    for(int i=1;i<=cnt;i++)        printf("%d ",prime[i]);    return 0;}
Ⅱ埃式筛

2.拓展欧几里得算法

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;int x,y;int exgcd(int a,int b){    if(!b)    {        x=1;        y=0;        return a;    }    else    {        int t;        int d=exgcd(b,a%b);        t=x;        x=y;        y=t-a/b*x;        return d;    }}int main(){    int a,b;    scanf("%d%d",&a,&b);    exgcd(a,b);//  cout<<__gcd(a,b)<<endl;    cout<<x<<" "<<y<<endl;    return 0;}

3.gcd+lcm

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;int gcd(int a,int b){    if(!b) return a;    else return gcd(b,a%b);}int lcm(int a,int b){    return a/gcd(a,b)*b;}int main(){    int a,b;    scanf("%d%d",&a,&b);    cout<<gcd(a,b)<<" "<<lcm(a,b)<<endl;    return 0;}

4.分解质因数

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;int main(){    long long n;    scanf("%lld",&n);    for(long long i=2;i<=n;i++)    {        while(n!=i)        {            if(n%i==0)            {                printf("%lld*",i);                n=n/i;                          }            else break;        }    }    printf("%lld",n);    return 0;} 

5.大数翻倍法

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;int a[233],mo[233];int gcd(int a,int b){    if(!b) return a;    else return gcd(b,a%b);} int lcm(int a,int b){    return a/gcd(a,b)*b;}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d%d",&a[i],&mo[i]);    int ans=0,nowmo=1;    for(int i=1;i<=n;i++)    {        int other=a[i],othermo=mo[i];        if(othermo>nowmo)        {            swap(ans,other);            swap(nowmo,othermo);        }        while(ans%othermo!=other)            ans+=nowmo;        nowmo=lcm(nowmo,othermo);     }    printf("%d",ans);}
4 0
原创粉丝点击