NOIP模板整理

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

图论:

1.最短路:

floyd
#include
#include
#include
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
#include
#include
#include
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]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
#include
#include
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]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
#include
#include
#include
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_queueq;
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
#include
#include
#include
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.cint 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
#include
#include
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]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
#include
#include
#include
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]int deepcha=deep[x]-deep[y];
    for(int i=0;i<=30;i++)
    {
        if(1<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;iscanf("%d%d%d",&u,&v,&c);
        build(u,v,c);
        build(v,u,c);
    }
    dfs(0,0);
    for(int i=0;i0]=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
#include
#include
#include
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
#include
#include
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
#include
#include
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*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*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
#include
#include
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(lint 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<" ";
    cout<printf("%lld",ans);
}
Ⅱ堆排序(小根)

①手打堆排序

#include
#include
#include
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]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]now])
        {
            if(heap[r]now]);
            now=l;
        }
        else if(heap[r]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
#include
#include
#include
using namespace std;
const int maxn=200005;
struct dqs
{
    int num;

};
bool operator<(dqs a,dqs b)
{
    return a.num>b.num;
}
priority_queueq;
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
#include
#include
#include 
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
#include
#include
#include
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)<
    cout<" "<return 0;
}

3.gcd+lcm

#include
#include
#include
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<" "<return 0;
}

4.分解质因数

#include
#include
#include
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
#include
#include
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);
}

你可能感兴趣的:(=====复习=====)