zoukankan      html  css  js  c++  java
  • 题解 P2296 【寻找道路】

    主要思路:DFS + Dijkstra + 堆优化 + 反向思维

    要不是写代码的时间问题我就用线段树优化

    首先,题目要求是路径上的所有点的出边所指向的点都直接或间接与终点连通。

    我们可以先不考虑如何通过某点到达终点,我们想象如果通过一个点可以再到达终点,说明把边反过来后,终点可以到达这个点。

    那我们可以建反边,通过DFS求出可以去向终点的点了。到达不了的不符合条件,我们可以直接删点了。

    dfs:

    int vis[mn];//表示是否去过
    void dfs(int x){
        if(vis[x]) return; vis[x] = 1;
        for (int i = hh[x]; i; i=ee[i].nxt) if (!vis[ee[i].v])
                dfs(ee[i].v);
        //printf("%d
    ", x);
    }
    

    我们如何删点?

    因为我们最终还是要跑最短路,所以我们就可以把这条边边权开到不可能到达的长度。

    像这样

    	go(x, 1, n, 1) 
            if (!vis[x]) 
                for (int i = hh[x]; i; i = ee[i].nxt) {
                    int v = ee[i].v;
                    for (int j = h[v]; j; j = e[j].nxt)
                        e[j].w = 100000;
                }
    

    然后把反向的边变成正边(我是直接存的两种边,其实都一样),然后跑Dijkstra + 堆优化就好了。注意,如果我们把边权值变化后就不能拿bfs像原来一样那么做了

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    #define go(i, j, n, k) for (int i = j; i <= n; i += k)
    #define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
    #define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
    #define mn 10010
    #define mm 200010
    #define inf 2147483647
    #define ll long long
    #define ld long double
    #define fi first
    #define se second
    #define root 1, n, 1
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define bson l, r, rt
    //#define LOCAL
    #define mod 
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    inline int read(){
        int f = 1, x = 0;char ch = getchar();
        while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    //This is AC head above...
    struct edge{
        int f, v, w, nxt;
        edge(int _f = 0, int _v = 0, int _w = 1, int _nxt = 0) : f(_f), v(_v), w(_w), nxt(_nxt){}
    } e[mm << 1], ee[mm << 1];
    int p, h[mn],pp,hh[mn];
    inline void add(int a, int b, int c = 1){
        e[++p].nxt = h[a], h[a] = p, e[p].f = a, e[p].v = b, e[p].w = c;
    }
    inline void fadd(int a,int b){
        ee[++pp].nxt = hh[a], hh[a] = pp, ee[pp].f = a, ee[pp].v = b;
    }
    //Dij + 堆优化
    struct node{
        int u,v;
        bool operator <(const node &b) const{
            return u > b.u;
        }
    };//重载运算符
    int n,m,s,t;
    int dis[mn];//起点到每个点的距离
    priority_queue<node> q;//优先队列
    inline void Dij(int s){//s为起点
        go(i, 0, n, 1)
            dis[i] = inf;
        dis[s] = 0;
        node o;
        o.u = 0;o.v = s;
        q.push(o);
        while (q.size()){
            int u = q.top().v, d = q.top().u;
            q.pop();
            if(d!=dis[u])
                continue;
            rep(i,u){
                int v = e[i].v, w = e[i].w;
                if (dis[v] > dis[u] + w){
                    dis[v] = dis[u] + w;
                    node p;
                    p.u = dis[v], p.v = v;
                    q.push(p);
                }
            }
        }
    }
    int vis[mn];
    void dfs(int x){
        if(vis[x]) return; vis[x] = 1;
        for (int i = hh[x]; i; i=ee[i].nxt) if (!vis[ee[i].v])
                dfs(ee[i].v);
        //printf("%d
    ", x);
    }
    inline void debug(){
        go(i, 1, p, 1) printf("%d->%d %d
    ", e[i].f, e[i].v, e[i].w);
        go(i, 1, pp, 1) printf("%d->%d %d
    ", ee[i].f, ee[i].v, ee[i].w);
    }
    int main(){
        n = read(), m = read();
        go(i,1,m,1){
            int a = read(), b = read();
            fadd(b, a);
            add(a, b);
        }
        s = read(), t = read();
        //debug();
        dfs(t);
        go(x, 1, n, 1) 
            if (!vis[x]) 
                for (int i = hh[x]; i; i = ee[i].nxt) {
                    int v = ee[i].v;
                    for (int j = h[v]; j; j = e[j].nxt)
                        e[j].w = 100000;
                }
        //debug();
        Dij(s);
        if(dis[t]!=inf)
            cout << dis[t];
        else
            cout << -1;
    #ifdef LOCAL
        Debug("
    My Time: %.3lfms
    ", (double)clock() / CLOCKS_PER_SEC);
    #endif
        return 0;
    }
    
    

    第十六次发题解,希望帮助同学们建立反向思维

  • 相关阅读:
    Dynamics AX 2012 R2 配置E-Mail模板
    Dynamics AX 2012 R2 设置E-Mail
    Dynamics AX 2012 R2 为运行失败的批处理任务设置预警
    Dynamics AX 2012 R2 耗尽用户
    Dynamics AX 2012 R2 创建一个专用的批处理服务器
    Dynamics AX 2012 R2 创建一个带有负载均衡的服务器集群
    Dynamics AX 2012 R2 安装额外的AOS
    Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录
    Dynamics AX 2012 R2 从代码中调用SSRS Report
    Dynamics AX 2012 R2 IIS WebSite Unauthorized 401
  • 原文地址:https://www.cnblogs.com/yizimi/p/10056277.html
Copyright © 2011-2022 走看看