zoukankan      html  css  js  c++  java
  • 【最短路-负环】Extended Traffic LightOJ

    Extended Traffic LightOJ - 1074

    题意:

    (n)个路口,每一个路口有一个拥挤度(A_i),从一个路口(I)到另一个路口(J)的收益为:((A_J−A_I)^3)。问从第(1)个路口到达第(k)个路口的最小收益。如果不能到达或收益<3,输出“?”,否则输出最小收益。

    思路:

    注意到路径收益可能是负的,也就是说需要判负环。Dijkstra会死循环,Floyd可能超时,只能SPFA。模板中是遇到迭代次数>n的节点就判定存在负环然后return,这里要稍微改动一下,需要将这个节点及与其相连的其它节点全部设定为不可到达(因为该节点会不断更新其它相连节点,导致那些节点的d值不断减小)。

    这题两个教训:一是链式前向星的边数组可能要开到很大……比如这题开到了maxn*1000;二是memset初始化数组为INF时,可能不能正确判断d[i]==INF,还是用for循环初始化吧

    int num = 0;
    int n, m;
    int head[maxn];
    bool done[maxn];
    LL d[maxn];
    LL busy[maxn];
    int cnt[maxn];
    bool can_reach[maxn];
    
    
    struct Edge {
        int next, to;
        LL dis;
    }edges[maxn*1000];
    
    void add_edge(int from, int to, LL dis) {
        num++;
        edges[num].next = head[from];
        edges[num].to = to;
        edges[num].dis = dis;
        head[from] = num;
    }
    
    void dfs(int u) {
        //由于d值为负的节点会不断更新其他与其相连的其它节点
        //所以与其相连或间接相连的点要全部改为不可到达
        for (int i = head[u]; i != 0; i = edges[i].next) {
            int v = edges[i].to;
            if (!can_reach[v]) continue;
            can_reach[v] = false;
            dfs(v);
        }
    }
    
    void spfa(int s) {
        queue<int> q;
        d[s] = 0;
        done[s] = true;
        q.push(s);
        cnt[s]++;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            done[u] = false;
            if (!can_reach[u]) continue;
            for (int i = head[u]; i != 0; i = edges[i].next) {
                Edge& e = edges[i];
                if (d[u] < INF && d[u] + e.dis < d[e.to]) {
                    d[e.to] = d[u] + e.dis;
                    if (cnt[e.to] > n) {
                        dfs(e.to);
                        can_reach[e.to] = false;
                        continue;
                    }
                    if (!done[e.to]) {
                        q.push(e.to);
                        done[e.to] = true;
                        ++cnt[e.to];
                    }
                }
            }
        }
    }
    
    void init() {
        num = 0;
        memset(head, 0, sizeof(head));
        for (int i = 0; i <= n; i++) d[i] = INF;
        memset(done, false, sizeof(done));
        memset(edges, 0, sizeof(edges));
        memset(busy, 0, sizeof(busy));
        memset(cnt, 0, sizeof(cnt));
        memset(can_reach, true, sizeof(can_reach));
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        FILE* stream1;
      //  freopen_s(&stream1, "output.txt", "w", stdout);
        int t; cin >> t; for(int kase=1;kase<=t;kase++) {
            cin >> n;
            init();
            cout << "Case " << kase <<":" << endl;
            for (int i = 1; i <= n; i++) cin >> busy[i];
            cin >> m;
            for (int i = 1; i <= m; i++) {
                int u, v;
                LL dis;
                cin >> u >> v;
                dis = busy[v] - busy[u];
                dis = dis * dis * dis;
                add_edge(u, v, dis);
            }
            spfa(1);
            int ask;
            cin >> ask;
            while (ask--) {
                int end;
                cin >> end;
                if (!can_reach[end] || d[end] < 3 || d[end] == INF) cout << "?" << endl;
                else cout << d[end] << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【并查集】亲戚
    【图论】Car的旅行线路 NOIP 2001
    【贪心】排座椅
    【DP】花店橱窗布置
    【NOIP】NOIP考纲总结+NOIP考前经验谈
    【NOIP】考前须知
    NOIP 2016 PJ T4 魔法阵
    NOIP 2016 PJ T3 海港
    【高精度】麦森数 NOIP 2003
    【带权并查集】食物链 NOIP 2001
  • 原文地址:https://www.cnblogs.com/streamazure/p/13419631.html
Copyright © 2011-2022 走看看