IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 洛谷P1967 [NOIP2013 提高组] 货车运输(最大生成树+LCA) -> 正文阅读

[数据结构与算法]洛谷P1967 [NOIP2013 提高组] 货车运输(最大生成树+LCA)

题目
思路
由题可知,我们要求的是最大载重,而且这个最大载重要适用于每条边,所以毫无疑问这是个求最小的最大问题。这时候我们应该构建最大生成树。得到了这样一个树之后,我们便考虑如何求出两个节点之间最小边权的最大值(即为题中的最大载重),因为这两点之间的路径是唯一的,我们只需要找出这条路径便可以得到答案,a,b两点有且只有一条路径连通,我们可以通过LCA将a,b两点连的路都走一遍,并且每经过每条路都对限重进行比较,以保证求得最大限重。
代码如下

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
int n,m;
struct Edge
{
    int from,to,dist;
}Edges[maxn];
int cnt=0;
int f[maxn];
vector<Edge>edges;
vector<int>G[maxn];
void add(int from,int to,int dist)
{
    edges.push_back({from,to,dist});
    int m=edges.size();
    G[from].push_back(m-1);
}

bool cmp(Edge a,Edge b)
{
    return a.dist>b.dist;
}

int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

void kruskal()
{
    sort(Edges+1,Edges+1+cnt,cmp);
    for(int i=1;i<=n;i++)
        f[i]=i;
    for(int i=1;i<=m;i++)
    {
        int x=find(Edges[i].from),y=find(Edges[i].to);
        if(x!=y)
        {
           // cout<<Edges[i].dist<<endl;
            f[x]=y;
            add(Edges[i].from,Edges[i].to,Edges[i].dist);
            add(Edges[i].to,Edges[i].from,Edges[i].dist);
        }
    }
}

int F[maxn][21],W[maxn][21],deep[maxn];
bool vis[maxn];

void dfs(int u,int fa,int d)
{
    vis[u]=true;
    deep[u]=deep[fa]+1;
    F[u][0]=fa;
    W[u][0]=d;
    for(int i=1;(1<<i)<=deep[u];i++)
    {
        F[u][i]=F[F[u][i-1]][i-1];
        W[u][i]=min(W[u][i-1],W[F[u][i-1]][i-1]);
    }
    for(int i=0;i<G[u].size();i++)
    {
        Edge e=edges[G[u][i]];
        int v=e.to;
        if(vis[v])
            continue;
        dfs(v,u,e.dist);
    }
}

int LCA(int x,int y)
{
    if(find(x)!=find(y))
        return -1;
    int ans=inf;
    if(deep[x]>deep[y])
        swap(x,y);
    for(int i=20;i>=0;i--)
    {
        if(deep[F[y][i]]>=deep[x])
        {
            ans=min(ans,W[y][i]);//注意一定要先更新答案,再更新位置!!
             y=F[y][i];
        }

    }
    if(x==y)
        return ans;
    for(int i=20;i>=0;i--)
    {
        if(F[x][i]!=F[y][i])
        {
            ans=min(ans,min(W[x][i],W[y][i]));//注意一定要更新答案,再更新位置!!
            x=F[x][i];
            y=F[y][i];

        }
    }
    ans=min(ans,min(W[x][0],W[y][0]));  //更新此时x,y到公共祖先最大载重,fa[x][0], fa[y][0]即为公共祖先 
    return ans;
}

int main()
{

    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y,z;
        scanf("%d %d %d",&x,&y,&z);
        Edges[++cnt].from=x;
        Edges[cnt].to=y;
        Edges[cnt].dist=z;
    }
    kruskal();
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            deep[i]=0;
            dfs(i,i,inf);
            F[i][0]=i;
            W[i][0]=inf;
        }
    }
    int q;
    cin>>q;
    for(int i=0;i<q;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        cout<<LCA(x,y)<<endl;
    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-04 11:17:09  更:2022-02-04 11:18:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:35:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码