Travel hnoi省选集训


Dijstra,Kruskal,在线LCA,树上倍增,手写堆【╮(╯▽╰)╭被stl嘲讽了】。


#include<map>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)

const int MAXM = 200005,MAXN = 100005,logN = 18;
const long long INF = 2e16;

int n, m;

struct Edge_list{int v , next;long long w;}edge[MAXM<<1] = {0};
int head[MAXN] = {0},el = 0;

struct Edge_star{int u , v ;long long w;}side[MAXM<<1] = {0};
int sl = 0;

int gfa[MAXN] = {0} , tfa[MAXN][logN] = {0};
int  dep[MAXN] = {0};long long tmax[MAXN][logN] = {0};

char cli[MAXN] = {'\0'};
bool crl[MAXN] = {false};

int heap[MAXN] = {0},site[MAXN] = {0}, hl;long long dist[MAXN] = {0};
int from[MAXN] = {0};bool flag[MAXN] = {0};

bool starcmp(const Edge_star &a,const Edge_star &b){return (a.w<b.w);}

void newedge(int u,int v,long long w)
{
    ++el,edge[el].v = v, edge[el].w = w;
    edge[el].next = head[u],head[u] = el;
}
int find_fa(int a)
{
    if(a == gfa[a])return a;
    else 
    {
     gfa[a] = find_fa(gfa[a]);
     return gfa[a];
    }
}

void update(int x){site[heap[x]] = x;}

void flood(int a)
{
    int min = a;

    if(L(a) <= hl && dist[heap[L(a)]] < dist[heap[min]])min = L(a);
    if(R(a) <= hl && dist[heap[R(a)]] < dist[heap[min]])min = R(a);

    if(min != a)
    {
      std::swap(heap[min],heap[a]); 
      update(min); update(a); 
      flood(min);
    }
}
void climb(int a)
{
    if(a == 1)return;

    int fa = a>>1;

    if(dist[heap[a]] < dist[heap[fa]])
    {
      std::swap(heap[fa],heap[a]);
      update(fa);update(a);
      climb(fa);
    }
}
void inheap(int x)
{   
    heap[++hl] = x;
    update(hl);
    flag[x] = true; 
    climb(hl);          
}
int outheap()
{
    int ret = heap[1];

    heap[1] = heap[hl];
    heap[hl--] = 0;
    flag[ret] = false;
    site[ret] = 0;
    update(1);

    flood(1);

    return ret;
}
void Dijstra()
{
    hl = 0;
    for(int i = 1 ;i <= n ;i++)dist[i] = INF;

    for(int i = 1 ;i <= n ;i++)
     if(crl[i]==true)
      {
       dist[i] = 0;
       from[i] = i;
        heap(i); 
       }

    for(int j = 1; j <= n ; j++)
    {
        int u = outheap();

        for(int i = head[u]; i ; i = edge[i].next)
        {
            int v = edge[i].v;
            long long tmp = dist[u] + edge[i].w;
            if(tmp < dist[v])
            {
                dist[v] = tmp;
                from[v] = from[u];

                if(flag[v] == true)climb(site[v]);
                else  inheap(v);
            }
        }
    }
}
void newgraph()
{
    for(int i = 1 ; i <= n ; i++)
      for(int j = head[i]; j ; j = edge[j].next)
      {
        int p = edge[j].v;
        if(from[i] < from[p])
       {
        ++sl;
        side[sl].u = from[i], side[sl].v = from[p];
        side[sl].w = dist[i] + dist[p] + edge[j].w;
       }
      }
    for(int i = 1 ; i <= n ; i++)head[i] = 0;
    el = 0;//clear edge  
}
void Kruskal()
{
    int cnt = 0;

    for(int i = 1 ; i <= n ; i++)
      if(crl[i] == true)gfa[i] = i, cnt++;

    std::sort(side+1,side+sl+1,starcmp);

    for(int i = 1 ; i <= sl ;i++)
    {
        int fu = find_fa(side[i].u);
        int fv = find_fa(side[i].v);

        if(fu != fv)
        {
          newedge(side[i].u,side[i].v,side[i].w);
          newedge(side[i].v,side[i].u,side[i].w);

          if(fu > fv)std::swap(fu,fv);

          gfa[fv] = fu;
        }
        if((el>>1) == cnt - 1)return;
    }
    return;//failed    
}
void buildtree(int a)
{
    dep[a] = dep[tfa[a][0]]+1;

    for(int i = head[a]; i; i = edge[i].next)
    {
        int p = edge[i].v;
        if(p == tfa[a][0])continue;

        tfa[p][0] = a; 
        tmax[p][0] = edge[i].w;
        buildtree(p);
    }
}
void getpre()
{
    for(int j = 1 ; j < logN; j++)
      for(int i = 1; i <= n; i++)
      {
        tfa[i][j] = tfa[tfa[i][j-1]][j-1];
        tmax[i][j] = std::max(tmax[tfa[i][j-1]][j-1],tmax[i][j-1]);
      }
}
long long getmax(int u,int v)
{
    long long ret = 0;

    if(dep[u]<dep[v])std::swap(u,v);//dep[u]>=dep[v]

    for(int i = logN - 1; i >= 0;i--)
      if(dep[tfa[u][i]] >= dep[v]) 
       {ret = std::max(ret,tmax[u][i]);  u = tfa[u][i];}

    if(u == v)return ret;  

    for(int i = logN - 1; i >= 0; i--)
       if(tfa[u][i]!=tfa[v][i])
      {
        ret = std::max(ret,tmax[u][i]);
        ret = std::max(ret,tmax[v][i]);
         u = tfa[u][i], v = tfa[v][i];
      }
    ret = std::max(ret,std::max(tmax[u][0],tmax[v][0]));

    return ret;     
}
char cc;
void scan(int &x)
{
    x = 0;
    do{cc = getchar();}while(!(cc >= '0' && cc <= '9'));
    do{
      x = (x<<3) + (x<<1) + cc - '0';
      cc = getchar();
      }while(cc >= '0' && cc <= '9');
}
char ss[15];short cl = 0;
void print(int x)
{
    while(x){ss[++cl] = x%10 + '0';x/=10;}
    while(cl){putchar(ss[cl--]);}puts("");
}
int main()
{
    int st;

#ifndef ONLINE_JUDGE
    freopen("travel.in","r",stdin);
    freopen("travel.out","w",stdout);
#endif

    scan(n);scan(m);
    scanf("%s",cli+1);

    for(int i = n ;i >= 1;i--)
    {
        if(cli[i]=='0')crl[i] = false;
        else     st = i,crl[i] = true;
    }

    for(int i = 1 ; i <= m ;i++)
    {
        int u,v,w; scan(u); scan(v); scan(w);
        newedge(u,v,w); newedge(v,u,w);
    }

    Dijstra();
    newgraph();
    Kruskal();

    tfa[st][0] = 0;
    tmax[st][0] = 0;
    buildtree(st);

    getpre();

    int q; scan(q);

    while(q--)
    {
        int u,v; scan(u); scan(v);
        print(getmax(u,v));
    }
#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
}

08-11 1139
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值