首页 > 其他分享 >ABC250H 题解

ABC250H 题解

时间:2024-07-24 14:30:07浏览次数:13  
标签:ABC250H int 题解 rightsquigarrow edge xrightarrow find dis

题面

我们先考虑如何让连续的不在房子中的时间尽量短:

我们考虑两个有房子的点 \(x,y\),如果 \(x\rightsquigarrow u\xrightarrow{w} v\rightsquigarrow y\) 这条路径上除了 \(x,y\) 不存在有房子的点,那么我们可以找到这样一条路径,一定不劣:

令 \(a,b\) 分别为最靠近 \(u,v\) 的有房子的点,那么存在 \(x\rightsquigarrow u\xrightarrow{w} v\rightsquigarrow b\rightsquigarrow v\xrightarrow{w} u\rightsquigarrow a\rightsquigarrow u\xrightarrow{w} v\rightsquigarrow y\) 这样一条路径,并且相邻两个有房子的点 \(x,b,a,y\) 之间路径长度显然小于 \(x\rightsquigarrow u\xrightarrow{w} v\rightsquigarrow y\)。

证明就是 \(dis(x,u)\ge dis(x,a),dis(y,v)\ge dis(b,v)\),分别比较一下就行了。

注意这道题是查询某情况下 \(x\) 和 \(y\) 是否联通,可以考虑动态加边然后并查集维护。

然后我们考虑:一条 \(u\xrightarrow{w} v\) 的边什么时候应该被加入图中?

经过上面的贪心,我们可以大概猜到答案是当 \(t\geq dis(a,u)+w+dis(v,b)\) 时。

接下来说明这个结论是对的:

首先,一定不存在经过 \(u\xrightarrow{w} v\) 的路径,且 \(t<dis(a,u)+w+dis(v,b)\),证明显然。

然后对于一条经过 \(u\xrightarrow{w} v\) 的路径,且这条边是耗时最长的,一定可以构造出 \(t=dis(a,u)+w+dis(v,b)\) 的答案:

设一条路径上的点为 \(x,u_1,u_2,\cdots,u_d,y\),设 \(v_i\) 为离 \(u_i\) 最近的有房子的点,那么新路径 \(x,u_1,v_1,u_1,u_2,v_2,u_2,\cdots,u_{d-1},v_{d-1},u_{d-1},y\) 上的 \(t\) 就是各边的加入时间的最大值(\(\max_{i=1}^{d-1}(dis(v_i,u_i)+dis(u_i,u_{i+1})+dis(u_{i+1},v_{i+1}))\))。

所以只要按照 \(dis(a,u)+w+dis(v,b)\) 排序,按询问的 \(t\) 逐次加入,并查集查询即可。

预处理到最近有房子的点的距离可以在 dijkstra 时把所有有房子的点先一起加入优先队列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 2e5 + 5, M = 4e5 + 5;
int fst[N], nxt[M], to[M], w[M], h = 2;
void add(int x, int y, int z)
{
    nxt[h] = fst[x], fst[x] = h, to[h] = y, w[h] = z, h ++;
}

int fa[N];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
inline void merge(int x, int y) {fa[find(x)] = find(y);}

int n, m, k;
ll dis[N];
void dij()
{
    using pii = pair<ll, int>;
    priority_queue<pii, vector<pii>, greater<pii>> q;
    memset(dis, 0x3f, sizeof dis);
    bool vis[N] = {};
    for(int i = 1; i <= k; i ++)
    {
        dis[i] = 0;
        q.push({0, i});
    }
    while(q.size())
    {
        int t = q.top().second; q.pop();
        if(vis[t]) continue;
        vis[t] = 1;
        for(int ei = fst[t], i = to[ei], w = ::w[ei]; ei; ei = nxt[ei], i = to[ei], w = ::w[ei])
        {
            if(dis[i] <= dis[t] + w) continue;
            dis[i] = dis[t] + w;
            q.push({dis[i], i});
        }
    }
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n >> m >> k;
    for(int i = 1; i <= n; i ++) fa[i] = i;
    for(int i = 1; i <= m; i ++)
    {
        int x, y, z; cin >> x >> y >> z;
        add(x, y, z);
        add(y, x, z);
    }
    dij();
    vector<pair<ll, int>> edge;
    for(int i = 2; i < h; i += 2)
        edge.push_back({dis[to[i]] + dis[to[i ^ 1]] + w[i], i});
    sort(edge.begin(), edge.end());
    auto it = edge.begin();
    int q; cin >> q;
    while(q --)
    {
        ll x, y, t;
        cin >> x >> y >> t;
        while(it != edge.end() && it->first <= t)
            merge(to[it->second], to[it->second ^ 1]), it ++;
        if(find(x) == find(y)) cout << "Yes\n";
        else cout << "No\n";
    }

    return 0;
}

扩展 CF1253F:从判定是否可行到变为求出 \(t\) 的最小值。

在这道题的基础上使用可撤销并查集加上整体二分即可解决。

标签:ABC250H,int,题解,rightsquigarrow,edge,xrightarrow,find,dis
From: https://www.cnblogs.com/adam01/p/18320841

相关文章

  • CF547D Mike and Fish 题解
    Description给定\(n\)个整点。你要给每个点染成红色或蓝色。要求同一水平线或垂直线上两种颜色的数量最多相差\(1\)。\(n,x_i,y_i\le2\times10^5\)。Solution考虑给每条水平线和垂直线建一个点,对于每个整点就把它对应的两条线连一条边。题目就转化为了给每条边定......
  • ARC117F Gateau 题解
    ARC117FGateau题解题解区好像都没有对dp详细解释,本文将稍细致地说一说dp部分。题目大意给定一个长度为\(2N\)的环,环上每个节点有属性值\(B_i\(i=0,\dots,2N-1)\)和\(2N\)个限制,第\(i\)个限制形如\(\sum\limits_{j=i}^{i+N-1}B_j\geqA_i\),向环上的节点赋值,使得......
  • 【保奖思路】2024年华为杯研究生数学建模D题解题思路分享(点个关注,后续会更新
    您的点赞收藏是我继续更新的最大动力!一定要点击如下的卡片链接,那是获取资料的入口!点击链接加入群聊【2024华为杯研赛资料汇】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=MwNruKbEvR9aZns1l7xXBWmQQKYAEh-F&authKey=igaBN79pz6BhNlDQ6TIZ5YFAbn71aDcYL77uANPquLF%2FTVgeSAhEZ......
  • 题解|2024暑期牛客多校03
    【原文链接】比赛链接:2024牛客暑期多校训练营3A.BridgingtheGap2题目大意nnn个人过河,第i......
  • P10280 [USACO24OPEN] Cowreography G 题解
    Description奶牛们组了一支舞蹈队,FarmerJohn是她们的编舞!舞蹈队最新而最精彩的舞蹈有\(N\)头奶牛(\(2\leN\le10^6\))排成一行。舞蹈中的每次动作都涉及两头奶牛,至多相距\(K\)个位置(\(1\leK<N\)),优雅地跳起并降落在对方的位置上。队伍中有两种奶牛——更赛牛(Guernsey)和荷......
  • 基因改造 题解
    前言题目链接:Hydro&bzoj。题意简述求匹配串\(S\)中和模式串\(T\)匹配的子串。两个串被定义为匹配的,当且仅当一个串任意交换字符后和另一个串相等。例如\(\texttt{12321}\)和\(\texttt{21312}\)匹配,因为前者交换\(\texttt{1}\)和\(\texttt{2}\)后与后者等价。当然......
  • CF521E Cycling City 题解
    Description给定一张\(n\)个点\(m\)条边的无向简单图。问图中能否找到两个点,满足这两个点之间有至少三条完全不相交的简单路径。\(n,m\le2\times10^5\),图不保证连通。Solution容易发现有解地充要条件是存在两个环有边交,考虑在dfs树上做这件事。注意到非树边一定......
  • CF1990F Polygonal Segments 题解
    题目链接:https://codeforces.com/contest/1990/problem/F赛时想到了一个略显抽象的做法,但因为写反了一个判断导致没能过掉。赛后调参卡过,用时\(3.5/8\)秒。为了不丢失这个idea最终还是决定写个题解记录一下。题意简述给定一个数组\(a_{1..n}\),执行以下查询:查询区间\([......
  • 题解:P10800 「CZOI-R1」卡牌
    \(\text{Link}\)最近做的最神金的一道数据结构题。题意给出\(m\)个值域为\([1,n]\)的四元组\(t_{i,0\sim3}\),定义四元组\(A\)胜于四元组\(B\)当且仅当最多存在一个\(j\in[0,3]\)使得\(A_j\leB_j\),求出有多少个值域为\([1,n]\)的四元组\(A\)胜于所有的\(t_{1......
  • 题解:P10717「KDOI-05」简单的树上问题
    \(\text{Link}\)题意给你一颗\(n\)个结点的树,有\(k\)次操作,第\(i\)次操作:每个点初始都处于未激活状态;以\(p_{i,j}\)的概率激活点\(j\);对于每个未激活的点\(i\),如果存在激活的结点\(j,k\)且\(i\)在\(j\)到\(k\)的路径上,则\(i\)也会被激活。给出\(v_{i......