Gym 101652T Security Badge (dfs)

原题地址:http://codeforces.com/gym/101652/attachments

题意:有 n 个点, m 条边,还有一个总上界 k ,你需要从 s 点走到t点,对于每条边 u , v , l , r ,你手中持有的权值需要在 [ l , r ] 的范围内才能从 u 走到 v ,问有多少种不同的权值可以成功地从 s 点走到 t

思路:一开始想的是从 [ 1 , k ] 这个范围开始进行 d f s ,最后每找到一个可行区间就存下来,最后对所有存下来的数据进行区间合并求最后的答案,然后写完发现 T 了,大概爆搜每次还要回溯太浪费时间了.

最后知道了一个很巧妙的判断方法,将每一扇们门的上下界都存储起来,我们可以知道,最终合法的若干区间的端点值一定来自于这些点,那么我们每次只需要暴力判断端点值了可不可行,那么就u能知道这个区间可不可行了.

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
int n, m, k, s, t;
struct edge {
    int u, v, l, r, nxt;
} e[maxn];
int tot, head[maxn];
void add_edge(int u, int v, int l, int r) {
    e[tot].v = v;
    e[tot].u = u;
    e[tot].l = l;
    e[tot].r = r;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

int a[maxn << 1];
int cnt, ans, vis[maxn];
void dfs(int u, int num) {
    vis[u] = 1;
    for (int i = head[u]; ~i; i = e[i].nxt) {
        int v = e[i].v;
        if (vis[v]) continue;
        if (e[i].l <= num && e[i].r >= num) dfs(v, num);
    }
}
int main() {
    scanf("%d%d%d%d%d", &n, &m, &k, &s, &t);
    CLR(head, -1);
    for (int i = 1; i <= m; i++) {
        int a1, b, c, d;
        scanf("%d%d%d%d", &a1, &b, &c, &d);
        add_edge(a1, b, c, d);
        a[cnt++] = c - 1;//这是为了计算单个点
        a[cnt++] = d;
    }
    sort(a, a + cnt);
    for (int i = 0; i < cnt; i++) {
        CLR(vis, 0);
        dfs(s, a[i]);
        if (vis[t]) ans += a[i] - a[i - 1];
    }
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81810131
今日推荐