zoukankan      html  css  js  c++  java
  • 寻找道路

    链接:https://ac.nowcoder.com/acm/problem/16498
    来源:牛客网

    题目描述

    在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
    1.路径上的所有点的出边所指向的点都直接或间接与终点连通。
    2.在满足条件1的情况下使路径最短。

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

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

    输入描述:

    第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边。
    接下来的m行每行2个整数x、y,之间用一个空格隔开,表示有一条边从点x指向点y。
    最后一行有两个用一个空格隔开的整数s、t,表示起点为s,终点为t。

    输出描述:

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

    输入

    复制
    3 2
    1 2
    2 1
    1 3

    输出

    复制
    -1

    说明

    如上图所示,箭头表示有向道路,圆点表示城市。起点1与终点3不连通,所以满足题目描述的路径不存在,故输出-1。

    示例2

    输入

    复制
    6 6
    1 2
    1 3
    2 6
    2 5
    4 5
    3 4
    1 5

    输出

    复制
    3

    说明

    如上图所示,满足条件的路径为1->3->4->5。注意点2不能在答案路径中,因为点2连了一条边到点6,而点6不与终点5连通。

    备注:

    对于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,把无法直接或间接连接终点的点排除,然后在利用spfa算法,求得最短路径。(spfa算法可以求得带负值的权边)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 300000;
     4 int dis[maxn], v[maxn],head[maxn], n, m, cnt;
     5 bool vis[maxn], ok[maxn];
     6 struct edge {
     7     int v, next;
     8 }e[maxn];        //
     9 
    10 void add(int x, int y)    //其实就是用一维数组达到领接表的一种方法
    11 {
    12     e[++cnt].v = y;        //cnt为第几条边,而v是后继
    13     e[cnt].next = head[x];    //将先前前继元素已经有的后继元素赋值给现在的后继元素
    14     head[x] = cnt;        //更新前继元素的后继元素
    15 }
    16 void spfa(int t)
    17 {
    18     memset(dis, 63, sizeof dis);
    19     memset(vis, 0, sizeof vis);
    20     queue<int>q;
    21     dis[t] = 0;
    22     vis[t] = 1;
    23     q.push(t);            //将源点让入队列中
    24     while (!q.empty())    //判断队列是否为空,为空就代表找到最短路径了
    25     {
    26         int u = q.front();    //将队首的点pop出来,并且将其周围的点进行比较
    27         q.pop();
    28         vis[u] = 0;
    29         for (int i = head[u]; i; i = e[i].next)
    30         {
    31             int v = e[i].v;                    //v代表所指向的点
    32             if (dis[v] > dis[u] + 1&&ok[v])        //如果这个点满足条件,就讲其放入队列中
    33             {
    34                 if (!vis[v]) {
    35                     q.push(v);
    36                     vis[v] = 1;
    37                 }
    38                 dis[v] = dis[u] + 1;
    39             }
    40         }
    41     }
    42 }
    43 
    44 void bfs(int t)        //正常的bfs
    45 {
    46     memset(v, 0, sizeof v);
    47     queue<int>q;
    48     q.push(t);
    49     ok[t] = v[t] = 1;
    50     while (!q.empty())
    51     {
    52         int u = q.front();
    53         q.pop();
    54         for (int i = head[u]; i; i = e[i].next)
    55         {
    56             int f = e[i].v;
    57             if (!v[f])
    58             {
    59                 ok[f]=v[f] = 1;
    60                 q.push(f);
    61             }
    62         }
    63     }
    64 }
    65 
    66 int main()
    67 {
    68     int s, t;
    69     scanf("%d%d", &n, &m);
    70     for (int i = 1; i <= m; i++)
    71     {
    72         int x, y;
    73         scanf("%d%d", &x, &y);
    74         add(y, x);
    75     }
    76     scanf("%d%d", &s, &t);
    77     bfs(t);
    78     for (int i = 1; i <= m; i++)
    79     {
    80         if (!v[i])
    81         {
    82             for (int j = head[i]; j; j = e[j].next)
    83             {
    84                 ok[e[j].v] = 0;
    85             }
    86         }
    87     }
    88     spfa(t);
    89     if (dis[s] >= 1061109567)
    90     {
    91         printf("-1");
    92         return 0;
    93     }
    94     printf("%d", dis[s]);
    95 }

    第一次写是看了题解写出来的,然后在今天再次刷一次,但还需要巩固

  • 相关阅读:
    初始FreeMake
    C#三层架构
    文件上传
    Jquery动画效果(混合)
    反射机制
    Java使用Sockt进行通信(2)
    Java使用Socket进行通信
    JavaScript基础
    Java的继承
    事物>视图>索引>备份和恢复
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/11671443.html
Copyright © 2011-2022 走看看