zoukankan      html  css  js  c++  java
  • [NOIP 2013]货车运输

    题目传送门

    因为要求最长集合线段中的最小值所以果断使用最大生成树,因为给定的是张图,无法确定唯一路径,而在树上就是了

    再去求相当于两点分别为端点的链上最小值

    以前写过树上路径,详情请点击(T1)

    所以这时就成了一道板子题了

    注意:这或许不仅仅只有一棵树,遍历找没有访问过的点重新当根即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    inline int read()
    {
        int f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    int f[10001],n,m;
    struct node{
        int u,v,w,nex;
    }x[50001];
    int head[10001],cnt;
    void add(int u,int v,int w)
    {
        x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
    }
    struct node1{
        int a,b,c;
    }s[50001];
    int sry;
    bool cmp(node1 x1,node1 x2)
    {
        return x1.c>x2.c;
    }
    int find(int x)
    {
        if(f[x]==x) return x;
        return f[x]=find(f[x]);
    }
    int fa[10001][21];
    int minn[10001][21],deep[10001];
    void dfs(int f,int fath)
    {  
        fa[f][0]=fath;
        deep[f]=deep[fath]+1;
        for(int i=1;(1<<i)<=deep[f];i++)
        {
            fa[f][i]=fa[fa[f][i-1]][i-1];
            minn[f][i]=min(minn[f][i-1],minn[fa[f][i-1]][i-1]);
        }
        for(int i=head[f];i!=-1;i=x[i].nex)
        {
            if(x[i].v==fath) continue;
            minn[x[i].v][0]=x[i].w;
            dfs(x[i].v,f);
        }
    }
    int q;
    int lca(int u,int v)
    {
        if(deep[u]==0||deep[v]==0) return -1;
        if(find(u)!=find(v)) return -1;
        int ans=2<<30-1;
        if(deep[u]<deep[v]) swap(u,v);
        for(int i=20;i>=0;i--)
            if(deep[u]-(1<<i)>=deep[v])
            {
                ans=min(ans,minn[u][i]);
                u=fa[u][i];
            }
        if(u==v)  return ans;
        for(int i=20;i>=0;i--)
        {
            if(fa[u][i]==fa[v][i]) continue;
            ans=min(ans,minn[u][i]),u=fa[u][i];
            ans=min(ans,minn[v][i]),v=fa[v][i]; 
        }
        ans=min(ans,minn[u][0]),u=fa[u][0];
        ans=min(ans,minn[v][0]),v=fa[v][0];
        return ans;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),m=read();
        for(int i=1;i<=n;i++) f[i]=i; 
        for(int i=1;i<=m;i++) s[i].a=read(),s[i].b=read(),s[i].c=read(); 
        sort(s+1,s+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            int t1=find(s[i].a),t2=find(s[i].b);
            if(t1!=t2)
            {
                f[t2]=t1;
                sry++;
                add(s[i].a,s[i].b,s[i].c),add(s[i].b,s[i].a,s[i].c);
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(deep[i]==0) dfs(i,0);
        } 
        q=read();
        for(int i=1;i<=q;i++)
        {
            int u=read(),v=read();
            printf("%d
    ",lca(u,v)); 
        }
    }
  • 相关阅读:
    UVALive-8077 Brick Walls 找规律
    UVALive-8079 Making a Team 排列组合公式化简
    UVALive-8072 Keeping On Track 树形dp 联通块之间缺失边的个数
    HDU-5534 Partial Tree 完全背包 设定初始选择
    HDU-2844 Coins 多重背包 物品数量二进制优化
    CodeForces-366C Dima and Salad 对01背包的理解 多个背包问题
    HDU-2955 Robberies 浮点数01背包 自变量和因变量位置互换
    UVALive-7197 Axles 动态规划 多个背包问题
    广义表(C++实现)
    稀疏矩阵及稀疏矩阵的压缩存储
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9550099.html
Copyright © 2011-2022 走看看