P1967 [NOIP2013 提高组] 货车运输

原题链接

题解

朴素做法:

每次询问,二分最小边,然后bfs遍历查看是否能到达,时间复杂度 O(qlognm)

优化:

如果答案里的最小边是 k ,那么代表所有边权不小于 k 的边都可以使用,因此可以直接从大到小加入边,直至起点与终点连接

时间复杂度 O(qmlogm)

这个做法虽然没有优化多少,但是这个思想给了我们启发,因为这个过程有点像求最大生成树的过程(这里的最大生成树是指树中最小的边最大)

而对于每一次查询,其实最大生成树是一样的,因此我们只需要在查询前求一次最大生成树,然后查询时在树上倍增求最大值(bfs做法)

时间复杂度 O(qlogm+nlogm)

码量有点大啊(汗)

更方便的做法:

在构建最大生成树时,如果当前遍历的边两端所属集合不同,那么查询中两点分别属于两端集合的答案就是当前边的权值(加边做法)

因此在构建最大生成树的时候,再建立一个集合维护待查询的编号,如果集合合并时有编号相同,更新答案

集合合并时小集合向大集合合并

code

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const ll inf=1e18;
const ll mod=1e9+7;

struct node
{
    ll x,y,v;
};

bool cmp(node a,node b)
{
    return a.v>b.v;
}

ll fa[10005];
ll finds(ll now){return fa[now]==now?now:fa[now]=finds(fa[now]);}


ll ans[50004];

void solve()
{
    memset(ans,-1,sizeof ans);
    ll n,m;
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
    {
        fa[i]=i;
    }

    vector<node> edge;

    for(ll i=1;i<=m;i++)
    {
        ll x,y,v;
        cin>>x>>y>>v;
        edge.push_back({x,y,v});
    }

    ll q;
    cin>>q;
    set<ll> Q[10004];
    for(ll i=1;i<=q;i++)
    {
        ll x,y;
        cin>>x>>y;
        Q[x].insert(i);
        Q[y].insert(i);
    }

    sort(edge.begin(),edge.end(),cmp);

    for(auto it:edge)
    {
        auto [x,y,v]=it;
        ll fx=finds(x),fy=finds(y);
        if(fx==fy) continue;
        if(Q[fx].size()>Q[fy].size()) swap(fx,fy);
        vector<ll> tem;
        for(auto it:Q[fx])
        {
            if(Q[fy].count(it))
            {
                ans[it]=v;
                Q[fy].erase(it);
            }
            else tem.push_back(it);
        }
        for(auto it:tem) Q[fy].insert(it);
        fa[fx]=fy;
    }

    for(ll i=1;i<=q;i++) cout<<ans[i]<<'\n';
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int TT=1;
    //cin>>TT;
    while(TT--) solve();
    return 0;
}

posted @   纯粹的  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示