20190807

本文深入探讨了倍增算法和堆算法在图论、最短路径和数据处理中的应用。通过具体实例,展示了倍增算法如何高效解决最近公共祖先(LCA)问题,以及堆算法在优先级队列管理和动态数据处理中的优势。文章覆盖了算法实现细节,包括初始化、遍历、查找和更新等关键步骤。

倍增:

T1:

#include <cstdio>
int w[100001][21],p[100001][21],head[1000001],deep[1000001],fa[1000001];
struct nodea{ int x,y,c; } t[1000001];
struct nodeb{ int x,y,c,g; } h[1000001];
int inf=999999999,len=0,n=0,m=0,q=0;
void px(int l,int r)
{
    int x=l,y=r,mid=t[(l+r)/2].c;
    while(x<=y)
    {
        while(t[x].c>mid)
        {
            x++;
        }
        while(t[y].c<mid)
        {
            y--;
        }
        if(x<=y)
        {
            nodea pt=t[x];
            t[x]=t[y];
            t[y]=pt;
            x++;
            y--;
        }
    }
    if(l<y)
    {
        px(l,y);
    }
    if(x<r)
    {
        px(x,r);
    }
}
int min(int x,int y)
{
    return x<y?x:y;
}
int init()
{
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
        head[i]=0;
        deep[i]=0;
    }
}
void ins(int x,int y,int c)
{
    len++;
    h[len].x=x;
    h[len].y=y;
    h[len].c=c;
    h[len].g=head[x];
    head[x]=len;
}
int find(int t)
{
    if(fa[t]==t)
    {
        return t;
    }
    else
    {
        return fa[t]=find(fa[t]);
    }
}
void kruskal()
{
    int p=0;
    for(int i=1;i<=m;i++)
    {
        int tx=find(t[i].x);
        int ty=find(t[i].y);
        if(tx!=ty)
        {
            fa[tx]=ty;
            ins(t[i].x,t[i].y,t[i].c);
            ins(t[i].y,t[i].x,t[i].c);
            p++;
            if(p==n-1)
            {
                break;
            }
        }
    }
}
void dfs(int u)
{
    for(int i=head[u];i>0;i=h[i].g)
    {
        int y=h[i].y;
        if(deep[y]==0)
        {
            deep[y]=deep[u]+1;
            p[y][0]=u;
            w[y][0]=h[i].c;
            dfs(y);
        }
    }
}
void ycl()
{
    for(int i=1;i<=n;i++)
    {
        if(deep[i]==0)
        {
            deep[i]=1;
            p[i][0]=0;
            dfs(i);
        }    
    }
    dfs(1);
    for(int i=1;i<=20;i++)
    {
        for(int x=1;x<=n;x++)
        {
            p[x][i]=p[p[x][i-1]][i-1];
            w[x][i]=min(w[x][i-1],w[p[x][i-1]][i-1]);
        }
    }
}
int lca(int x,int y)
{
    int ans=inf;
    if(deep[x]<deep[y])
    {
        int t=x;
        x=y;
        y=t;
    }
    for(int i=20;i>=0;i--)
    {
        if(deep[p[x][i]]>=deep[y])
        {
            ans=min(ans,w[x][i]);
            x=p[x][i];
        }
    }
    if(x==y)
    {
        return ans;
    }
    for(int i=20;i>=0;i--)
    {
        if(p[x][i]!=p[y][i])
        {
            ans=min(ans,min(w[x][i],w[y][i]));
            x=p[x][i];
            y=p[y][i];
        }
    }
    ans=min(ans,min(w[x][0],w[y][0]));
    return ans;
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&t[i].x,&t[i].y,&t[i].c);
    }
    px(1,m);
    init();
    kruskal();
    ycl();
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        int dx=0,dy=0;
        scanf("%d %d",&dx,&dy);
        if(find(dx)!=find(dy))
        {
            printf("-1\n");
        }
        else
        {
            printf("%d\n",lca(dx,dy));
        }
    }
    return 0;
}

T2:

#include<stdio.h> 
#include<algorithm>
#include<set>
#define go(i,a,b) for(int i=a;i<=b;i++)
#define ro(i,a,b) for(int i=a;i>=b;i--)
#define inf 2147483645
#define eps 0.000003
using namespace std;const int N=100005;
int n,m,s,h[N],des[N][2],Min[N][2],To[N][22],dis[N][22][2],tot[2],x;
struct info{int h,id;bool operator<(const info a)const{return h<a.h;};};
set<info>box;set<info>::iterator I;int A(int t){return t<0?-t:t;}
void consider(int i,info p)
{
    int j=p.id;
    if((A(h[i]-h[j])<Min[i][0])||(Min[i][0]==A(h[i]-h[j])&&h[j]<h[des[i][0]]))
    {
        if((Min[i][0]<Min[i][1])||(Min[i][1]==Min[i][0]&&h[des[i][0]]<h[des[i][1]]))
        Min[i][1]=Min[i][0],des[i][1]=des[i][0];
        Min[i][0]=A(h[i]-h[j]),des[i][0]=j;    
    }
    else if((A(h[i]-h[j])<Min[i][1])||(Min[i][1]==A(h[i]-h[j])&&h[j]<h[des[i][0]]))
    Min[i][1]=A(h[i]-h[j]),des[i][1]=j;    
}
void doubling(int i,int val)
{
    ro(k,20,0)if(dis[i][k][0]+dis[i][k][1]<=val&&To[i][k])
        val-=(dis[i][k][0]+dis[i][k][1]),
        tot[1]+=dis[i][k][1],tot[0]+=dis[i][k][0],i=To[i][k];    
    if(des[i][1]&&Min[i][1]<=val)tot[1]+=Min[i][1];
}
int main(){scanf("%d",&n);go(i,1,n)scanf("%d",&h[i]),Min[i][1]=Min[i][0]=inf;
    ro(i,n,1)
    {    
        box.insert((info){h[i],i});
        I=box.find((info){h[i],i});++I;
        if(I!=box.end())consider(i,*I),++I,I!=box.end()?consider(i,*I),1:1,--I;--I;
        if(I!=box.begin())--I,consider(i,*I),I!=box.begin()?--I,consider(i,*I),1:1;
    }
    go(i,1,n)To[i][0]=des[des[i][1]][0],
    dis[i][0][1]=Min[i][1],dis[i][0][0]=Min[des[i][1]][0];
    go(k,1,20)go(i,1,n)To[i][k]=To[To[i][k-1]][k-1],
    dis[i][k][1]=dis[i][k-1][1]+dis[To[i][k-1]][k-1][1],
    dis[i][k][0]=dis[i][k-1][0]+dis[To[i][k-1]][k-1][0];
    scanf("%d",&x);double rate=inf;int pos=0;h[0]=-inf;go(i,1,n)
    {
        tot[0]=tot[1]=0;doubling(i,x);double tmp=tot[0]?1.0*tot[1]/tot[0]:inf;
        if(tmp-rate<eps&&tmp-rate>-eps&&h[i]>h[pos])pos=i;
        if(rate-tmp>eps)pos=i,rate=tmp;
    }
    printf("%d\n",pos);scanf("%d",&m);go(i,1,m)
    {
        scanf("%d%d",&s,&x);
        tot[0]=tot[1]=0;doubling(s,x);
        printf("%d %d\n",tot[1],tot[0]);
    }
    return 0;
}

T3:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 55;

long long n,m,u,v,a[maxn][maxn][65]; 
long long f[maxn][maxn];
long long dis[maxn];
bool vis[maxn];

void spfa(int s){
    queue<int > q;
    for(int i=1;i<=n;i++){
        dis[i] = 1e9;
    }
    q.push(s);
    dis[s] = 0;
    vis[s] = 1;
    while(!q.empty()){
        int cur = q.front();
        q.pop();
        vis[cur] = 0;
        for(int v=1;v<=n;v++)
          if(f[cur][v] && dis[v] > dis[cur] + f[cur][v]){
            dis[v] = dis[cur] + f[cur][v];
            if(vis[v] == 0){
              vis[v]=1;
              q.push(v);
            }
        }
    }
}

int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%lld%lld",&u,&v);
        a[u][v][0] = 1;
    }
    for(int k=1;k<=64;k++)
      for(int j=1;j<=n;j++)
        for(int u=1;u<=n;u++)
          for(int v=1;v<=n;v++)
            if(a[u][j][k-1] && a[j][v][k-1])
              a[u][v][k]=1;

    for(int u=1;u<=n;u++)
      for(int v=1;v<=n;v++)
        for(int k=0;k<=64;k++)
          if(a[u][v][k]){
             f[u][v]=1;
             break;
          }
    spfa(1);
    printf("%lld",dis[n]);
    return 0;
}

堆:

T1:

#include<cstdio>  
#include<queue>   
using namespace std;
int a[100005]={}, b[100005]={}, to[100005]={},i, n;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > >q;
int main()
{
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (i = 1; i <= n; i++)
    {
        scanf("%d", &b[i]); to[i] = 1;
        q.push(pair<int, int>(a[1] + b[i], i));
    }
    while (n--)
    {
        printf("%d ", q.top().first);
        i = q.top().second; q.pop();
        q.push(pair<int, int>(a[++to[i]] + b[i], i));
    }
    return 0;
}

T2:

#include <cstdio>
#include <queue>
#define Qmax priority_queue<int>
#define Qmin priority_queue<int,vector<int>,greater<int> >
#define f(i , a , b) for(int i=(a) ; i <= (b) ; i++)
using namespace std;
inline int Input(){
    char C=getchar();
    int N=0 , F=1;
    while(('0' > C || C > '9') && (C != '-')) C=getchar();
    if(C == '-') F=-1 , C=getchar();
    while('0' <= C && C <= '9') N=(N << 1)+(N << 3)+(C - 48) , C=getchar();
    return F*N; 
}
int main(){
    int a[200001];
    Qmax A;
    Qmin B;
    int n=Input() , m=Input() , r=1 , q;
    f(i , 1 , n) a[i]=Input();
    f(i , 1 , m){
        q=Input();
        f(j , r , q){
            A.push(a[j]);
            if(A.size() == i) B.push(A.top()) , A.pop();
        }
        r=q+1;
        printf("%d\n" , B.top()); 
        A.push(B.top()) , B.pop(); 
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值