• NOIP2014 寻找道路


    题目描述 Description

    在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:

    1.路径上的所有点的出边所指向的点都直接或间接与终点连通。

    2.在满足条件1的情况下使路径最短。

    注意:图G中可能存在重边和自环,题目保证终点没有出边。

    请你输出符合条件的路径的长度。

    输入描述 Input Description

    第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。

    接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。

    最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。

    输出描述 Output Description

    输出文件名为road.out。

    输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出-1。

    样例输入 Sample Input

    road.in

    road.out

    3 2

    1 2

    2 1

    1 3

    -1

    样例输出 Sample Output

    road.in

    road.out

    6 6

    1 2

    1 3

    2 6

    2 5

    4 5

    3 4

    1 5

    3

    数据范围及提示 Data Size & Hint

    对于30%的数据,0< n ≤10,0< m ≤20;

    对于60%的数据,0< n ≤100,0< m ≤2000;

    对于100%的数据,0< n ≤10,000,0< m ≤200,000,0< x,y,s,t≤n,x≠t。

    思路:

    分析问题,做的最短路中的点既能从起点出发,又能从终点回来,所以先预处理,有两种方式,可以先在起点进行一遍bfs,把在没到终点前就没有出边的点标记下,然后再沿着反图进行一遍bfs,或者可以直接从终点出发在反图进行一遍bfs,把没涉及到的点标出来,然后再在反图bfs,最后最短路

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn = 200005,maxnum = 100000;
    int dist[maxn],jud[maxn],q[maxn],start[maxn],tnum[maxn],fjud[maxn],cuter[maxn],n,m,x,t,ans,num = 0;
    
    struct star{
        int next;
        int to;
        int p;
    };
    star edge[maxn];
    
    void dfs(int node){
        int head = 1,tail = 1,bq[maxn];
        fjud[node] = 0;
        bq[1] = node;
        while(head <= tail){
            int now = bq[head];
            for(int i = start[now];i != -1;i = edge[i].next){
                if(fjud[edge[i].to]){
                    tail = (tail + 1) % maxn;
                    bq[tail] = edge[i].to;
                    fjud[edge[i].to] = 0;
                }
            }
            head = (head + 1) % maxn;
        }
    }
    
    void dfs1(int node){
        int head = 1,tail = 1,bq[maxn];
        cuter[node] = 0;
        bq[1] = node;
        while(head <= tail){
            int now = bq[head];
            for(int i = start[now];i != -1;i = edge[i].next){
                if(cuter[edge[i].to]){
                    bq[tail] = edge[i].to;
                    cuter[edge[i].to] = 0;
                }
            }
            head = (head + 1) % maxn;
        }
    }
    
    int spfa(int u,int v){
        dist[u] = jud[u] = 0;
        q[1] = u;
        int head = 1,tail = 1;
        while(head <= tail){
            int now = q[head];
            for(int i = start[now];i != -1;i = edge[i].next){
            
                if(dist[edge[i].to] > dist[now] + edge[i].p && cuter[edge[i].to]){
                    dist[edge[i].to] = dist[now] + edge[i].p;
                    if(jud[edge[i].to]){
                    tail = (tail + 1) % maxn;
                    q[tail] = edge[i].to;
                    jud[edge[i].to] = 0;
                    }
                }
            }
            
            head = (head + 1) % maxn;
            jud[now] = 1;
        }
        if(dist[v] == 100000) return -1;
        return dist[v];
    }
    
    int main(){
        cin>>n>>m;
        int u,v,p;
        for(int i = 1;i <= n;i++){
            start[i] = -1;
            dist[i] = maxnum;
            jud[i] = 1;
            fjud[i] = 1;
            cuter[i] = 1;
            tnum[i] = 0;
            
        }
        int cnt = 1;
        for(int i = 1;i<= m;i++){
            cin>>u>>v;
            swap(u,v);
            edge[i].p = 1;
            edge[i].to = v;
            edge[i].next=start[u];
            cnt++;
            start[u] = cnt - 1;
            tnum[u]++; 
        }
        cin>>x>>t;
        dfs(t);
        for(int i = 1;i <= n;i++) if(fjud[i]) dfs1(i);
        cuter[x]= cuter[t] = 1;
        ans = spfa(t,x);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Linux 上的数据可视化工具
    LINUX 暂停、继续进程
    77个常用Linux命令和工具
    必学100个常用linux命令大全
    Canny边缘检測算法原理及其VC实现具体解释(一)
    ACM POJ 2192 Zipper
    【实战】静默安装-oracle 11.2.0.3 on centos 5.10
    C++ 观察者模式样例
    access数据库:怎么直接从access里把数据里同样的文字替换成空字符&quot;&quot;
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
  • 原文地址:https://www.cnblogs.com/hyfer/p/5812619.html
Copyright © 2020-2023  润新知