Gym 101617H

/*
    这道题的题意简单,有n个点,m条单项边,每条边有一个范围限定,要通过这个条边的人的标号要在这个范围之内(min<=k<=max)
    问最后从s到t能有多少人可以到达
    一开始的想法全都是想着怎么从起点带着区间[1,k]一路区间交并到最后终点这种做法,dfs肯定不行,bfs又没法让区间状态合并
    应对不来有环的情况
    正解是一个非常巧妙的方法。因为最后到达终点的区间肯定是前面出现过的区间的端点组合而成的,这里我们就可以先离散化,然后
    枚举两个相邻的端点来跑一边dfs来判断这个区间能否最后到达终点来产生贡献
*/
import java.util.LinkedList;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    static final int MAXN = (int) (1e3 + 10);
    static int n, m, k;
    static int s, t;

    static class Edge {
        int v;
        int l, r;

        public Edge(int v, int l, int r) {
            this.v = v;
            this.l = l;
            this.r = r;
        }

        public Boolean pass(int l, int r) {//判断能否通过
            return (this.l <= r && this.r >= r);
        }
    }

    static LinkedList<Edge>[] G;
    static Boolean[] vis;

    static Boolean dfs(int u, int l, int r) {
        if (u == t)
            return true;
        vis[u] = true;
        Boolean pass = false;
        for (Edge edge : G[u]) {
            if (vis[edge.v] != null)
                continue;
            if (edge.pass(l, r))
                pass |= dfs(edge.v, l, r);
        }
        return pass;
    }

    static Boolean Range_Arrive(int l, int r) {
        vis = new Boolean[MAXN];
        return dfs(s, l, r);
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        n = cin.nextInt();
        m = cin.nextInt();
        k = cin.nextInt();
        s = cin.nextInt();
        t = cin.nextInt();
        G = new LinkedList[MAXN];
        Set<Integer> set = new TreeSet<>();
        int cnt = 0;
        for (int i = 1; i <= n; i++)
            G[i] = new LinkedList<>();
        for (int i = 0; i < m; i++) {
            int a, b, l, r;
            a = cin.nextInt();
            b = cin.nextInt();
            l = cin.nextInt();
            r = cin.nextInt();
            G[a].add(new Edge(b, l, r));
            set.add(l);
            set.add(r + 1);//注意这里区间要转化成左闭右开
        }
        Integer l = null;
        int ans = 0;
        for (Integer r : set) {
            if (l == null) {
                l = r;
            } else {
                // System.out.println("r="+r+":l="+l);
                if (Range_Arrive(l, r - 1))
                    ans += r - l;//这样记录答案就不会产生重叠
                l = r;
            }
        }
        System.out.println(ans);
    }
}
发布了75 篇原创文章 · 获赞 14 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq965194745/article/details/78589995