luogu1967noip2013 货车运输 [生成树kruskal LCA ]

Posted lxyyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu1967noip2013 货车运输 [生成树kruskal LCA ]相关的知识,希望对你有一定的参考价值。

P1967 货车运输
最大生成树+倍增算路径最小值

最大生成树就是kruskal时将边改为降序 然后就和普通kruskal一样

然后就是用的LCA倍增模板中说的其它骚操作一样

可以在预处理的时候还可以顺便记录下这段路径的权值最大值 最小值或者权值和之类的信息,这样就可以在O(logn)的时间内求出树上两点间路径权值的最大值、最小值还有权值和

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;
#define ll long long
#define rg register
const int N=100000+5,M=500000+5,inf=0x3f3f3f3f,P=19650827;
int n,m,q;
int dep[N],p[N][25],w[N][25];
template <class t>void rd(t &x)
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch==-,ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;


int head[N],tot=0,ans;
struct edgeint v,nxt,w;e[M];
void add(int u,int v,int w)
    e[++tot]=(edge)v,head[u],w;head[u]=tot;


int f[N];
struct node
    int u,v,w;
nd[M];
bool cmp(node a,node b)return a.w>b.w;
int find(int x)return f[x]==x?x:f[x]=find(f[x]);
void kruskal()
    int cnt=0;
    for(rg int i=1;i<=n;++i) f[i]=i;
    for(rg int i=1,u,v,w;i<=m;++i)
        u=nd[i].u,v=nd[i].v,w=nd[i].w;
        if(find(u)!=find(v))
            f[f[u]]=f[v];
            ++cnt;
            add(u,v,w),add(v,u,w);
            if(cnt==n-1) break;
        
    


void dfs(int u)
    for(int i=head[u],v;i;i=e[i].nxt)
        v=e[i].v;
        if(!dep[v])//未走过 
            dep[v]=dep[u]+1;
            p[v][0]=u;
            w[v][0]=e[i].w;
            dfs(v);
        
    

void build()
    for(rg int i=1;i<=n;++i)
        if(!dep[i])
            dep[i]=1;
            p[i][0]=0;
            dfs(i);
        
    
    dfs(1);//连起来
    for(int i=1; i<=20; i++)
        for(int j=1; j<=n; j++)
            p[j][i]=p[p[j][i-1]][i-1]; 
            w[j][i]=min(w[j][i-1], w[p[j][i-1]][i-1]);
        


int LCA(int a,int b)
    ans=inf;
    if(dep[a]>dep[b]) swap(a,b);
    for(int i=20;i>=0;--i)
        if(dep[p[b][i]]<dep[a]) continue;
        ans=min(ans,w[b][i]);b=p[b][i];
    
    if(a==b) return ans;
    for(int i=20;i>=0;--i)
        if(p[a][i]==p[b][i]) continue;
        ans=min(ans,min(w[a][i],w[b][i]));
        a=p[a][i],b=p[b][i];
    
    ans=min(ans,min(w[a][0],w[b][0]));
    return ans;


int main()
    //freopen("in.txt","r",stdin);
    memset(dep,0,sizeof(dep));
    memset(p,0,sizeof(p));
    rd(n),rd(m);
        int u,v,w;
    for(rg int i=1;i<=m;++i)
        rd(u),rd(v),rd(w);
        nd[i]=(node)u,v,w;
    
    sort(nd+1,nd+1+m,cmp);
    kruskal();
    build();
    rd(q);
    for(rg int i=1;i<=q;++i)
        rd(u),rd(v);
        if(find(u)!=find(v)) printf("-1\n");
        else printf("%d\n",LCA(u,v));
    
    return 0;

 

以上是关于luogu1967noip2013 货车运输 [生成树kruskal LCA ]的主要内容,如果未能解决你的问题,请参考以下文章

$Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

luogu1967[NOIP2013D1T3] 货车运输 (最大生成树+LCA)

noip-2013 货车运输

洛谷 1967 NOIP2013 货车运输

NOIP2013D1T3货车运输

NOIP2013提高组货车运输