首页 > 其他分享 >CF567E 题解

CF567E 题解

时间:2024-07-25 21:39:59浏览次数:14  
标签:CF567E int 题解 短路 vis push ll dis

题面

考虑如何一条边是必经之路:设 \(cntl_i\) 为从 \(s\) 到 \(i\) 走最短路的方案数,\(cntr_i\) 为从 \(i\) 到 \(t\) 最短路方案数。

由乘法原理,如果对于边 \(e_i=(u,v)\),\(cnt_t=cnt_u\times cntr_v\),则 \(e_i\) 是最短路上的必经边,输出 Yes 即可。

如果 \(cnt_u\times cntr_v=0\) 说明这条边不可能到达终点或不可达,输出 No

否则设最短路长 \(d\),从 \(s\) 到 \(i\) 最短路 \(disl_i\),从 \(i\) 到 \(t\) 最短路 \(disr_i\)。

对于边 \(e_i=(u,v)\) 设 \(delta = w+disl_u+disr_v-d+1\),若 \(w_i\leq dt\) 说明 \(w_i\) 再小也没用,输出 No。否则输出 \(\texttt{CAN } delta\)。

求终点相同的最短路和方案数只要建反图跑以原来终点为起点的最短路即可。

方案数在求最短路时可以和 dp 一样更新。


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

const int N = 1e5 + 5, p = 1e17 + 5;

ll dis[N], rdis[N], g[N], rg[N], n, m, s, t;
bool vis[N];
vector<pair<int, int>> e[N], e2[N];

void dij(ll *dis, ll *g, vector<pair<int, int>> *e, int s)
{
    using pii = pair<ll, int>;
    priority_queue<pii, vector<pii>, greater<pii>> q;
    q.push({0, s});
    memset(dis, 0x3f, sizeof ::dis);
    memset(vis, 0, sizeof vis);
    dis[s] = 0; 
    g[s] = 1;
    while(q.size())
    {
        int t = q.top().second; q.pop();
        if(vis[t]) continue;
        vis[t] = 1;
        for(auto [i, w] : e[t])
        {
            if(dis[i] < dis[t] + w) continue;
            if(dis[i] == dis[t] + w)
            {
                g[i] = (g[i] + g[t]) % p;
                continue;
            }
            g[i] = g[t];
            dis[i] = dis[t] + w;
            q.push({dis[i], i});
        }
    }
}

int u[N], v[N], w[N];
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    cin >> n >> m >> s >> t;
    for(int i = 1; i <= m; i ++)
    {
        int x, y, z; cin >> x >> y >> z;
        e[x].push_back({y, z});
        e2[y].push_back({x, z});
        u[i] = x, v[i] = y, w[i] = z;
    }
    dij(dis, g, e, s);
    dij(rdis, rg, e2, t);
    ll d = dis[t];
    for(int i = 1; i <= m; i ++)
    {
        if(dis[u[i]] + w[i] + rdis[v[i]] == d)
        {
            if((__int128)g[u[i]] * rg[v[i]] % p != g[t])
            {
                if(w[i] == 1) cout << "NO\n";
                else cout << "CAN " << 1 << "\n";
            }
            else cout << "YES\n";
        }
        else
        {
            ll dt = dis[u[i]] + w[i] + rdis[v[i]] - d;
            if(w[i] <= dt + 1) cout << "NO\n";
            else cout << "CAN " << dt + 1 << "\n";
        }
    }

    return 0;
}

标签:CF567E,int,题解,短路,vis,push,ll,dis
From: https://www.cnblogs.com/adam01/p/18324197

相关文章

  • 【题解】Solution Set - 杂题选讲「刘君实」
    https://www.becoder.com.cn/contest/5423「HNOI2012」集合选数感觉差不多会。7/25sh杂题听课情况NOI2018冒泡排序【40】几乎不会麦田里的守望者【40】打表找规律、最后dp不太理解星空列车【40】完全不会WereYouLast:知道怎么做,但是不知道为什么是对的A......
  • CF467E 题解
    题面给出这种限制,我们只能4个4个考虑。令\(f_i\)为考虑到\(a_i\),最长的\(b\)序列长\(4f_i\)。令\(mx_i\)为以\(a_i\)结尾的最短连续子序列包含\(x\y\x\y\)的(不一定连续的)结构的左端点。于是有\(f_i=\max_{j=1}^{mx_i-1}f_j+4\)。用前缀和优化:\(g_i=\max......
  • CF594A 题解
    题面来个不一样的证明。根据样例,我们可以有一个直觉:两点之间一定距离\(\fracn2\),答案为这样的点对之间\(\Deltax\)的最小值。直接交上去,发现这是对的。为什么呢?先证明上界:先手可以让答案小于等于两点距离\(\fracn2\)点对的\(\Deltax\)的最小值。这是容易的:先手只......
  • 题解:Codeforces Round 961 (Div. 2) B1&B2
    本题含有B1和B2两个难度版本。由于关系相近,我把他们放在同一篇博客中,可自行选择观看B1.Bouquet(EasyVersion)timelimitpertest:1.5secondsmemorylimitpertest:512megabytesinput:standardinputoutput:standardoutputThisistheeasyversionoftheprobl......
  • CF568C New Language 题解
    Description将\(\texttt{a}\sim\texttt{a}+l-1\)这\(l\)个字符分成\(\texttt{V,C}\)两个集合。你需要构造一个长度为\(n\)且满足\(m\)个限制且不小于另一个长度为\(n\)的字符串\(s\)的最小字符串。每一个限制为若字符串的第\(p_1\)个位置上的字符\(\in......
  • CF22E 题解
    题面注意到题目给的图为基环树森林。因为一个(\(n>1\))的强连通图每个点都要有出度和入度,所以:对于每个基环树,叶子结点是没有入度的,所以一定要有一条从环上出发的路径经过这个点。对于基环树的环,注意到它缩点后没有出度,所以一定要有一条出边。注意到叶子结点的需求和根节点相反,......
  • 题解:AT_arc116_e [ARC116E] Spread of Information
    题目链接思路看到最大值最小首先可以想到二分,发现答案具有单调性,那么思考如何在\(O(n)\)的时间内判断是否合法。考虑贪心,在最远没覆盖的点的距离和要判断的\(mid\)刚好相等的时侯再选择一定不劣,因为这样覆盖的点最多,那么从叶子节点向上回溯,处理它的所有儿子,判断是否选择该......
  • LG3107 [USACO14OPEN] Odometer S 题解 (数位DP+容斥)
    题意定义一个数是神奇的当且仅当这个数中有一个数位出现了一半及以上,比如112,2233。求\([l,r]\)中有多少个好的数字,\(100\lel,r\le10^{18}\)。题解考虑数位DP,先把答案转为\(Ans(r)-Ans(l-1)\),我们钦定一个数\(k\)让他必须出现多于一半,然后我们想求\([1,x]\)中有多少......
  • CF1015F 题解
    题面考虑这样的匹配问题,可以想如何确定第一次匹配,这样可以不重不漏地计数。考虑dp的时候同时维护有几个括号没有匹配,匹配到\(s\)的第几位,所以令\(f(i,j,k)\)表示dp到(要计数的序列的)第\(i\)个字符,有\(j\)个左括号没有匹配,匹配到\(s\)的第\(k\)位。转移很容易,考......
  • 程序设计:C++入门教程(速成) + 15道经典例题(附带例题解析)
    本文章以实用为主,若实在是不明白文字所表达的内容,无脑复制代码,自己动手运行一下,实验一下即可理解文章内容,放心,代码是全的,全选复制粘贴即可不废话,直接开整数据类型常用数据类型int:整数类型,用于表示整数值。例如:1,2,-3,0等。float:单精度浮点数类型,用于表示带有小数点的数......