• 2296 寻找道路


    2014 NOIP提高组 day2 第二题

    提交次数:3

    题目描述

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

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

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

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

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

    输入输出格式

    输入格式:

    输入文件名为road .in。

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

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

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

    输出格式:

    输出文件名为road .out 。

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

    代码:

     1 #include<iostream>
     2 #include<vector>
     3 #include<queue> 
     4 #include<cstdio>
     5 using namespace std;
     6 vector<int>v[10010];
     7 vector<int>vr[10010];//反置图 
     8 int used[10010];
     9 int can[10010];//能通向终点的点 
    10 queue<int>q;
    11 struct node{
    12     int num;
    13     int step;
    14 };
    15 queue<node>qq;
    16 
    17 int main(){
    18     int n, m;
    19     cin>>n>>m;
    20     int i;
    21     for(i = 1; i <= m; i++){
    22         int x, y;
    23         scanf("%d%d", &x, &y);
    24         v[x].push_back(y);
    25         vr[y].push_back(x);
    26     }
    27     int s, t;
    28     cin>>s>>t;
    29     q.push(t);
    30     can[t] = 1;
    31     int k;
    32     while(!q.empty()){
    33         k = q.front();
    34         q.pop();
    35         for(i = 0; i < vr[k].size(); i++){
    36             if(!can[vr[k][i]]){
    37                 q.push(vr[k][i]);
    38                 can[vr[k][i]] = 1;
    39             }                
    40         }
    41     }
    42     for(i = 1; i <= n; i++){
    43         if(!can[i]){
    44             for(int j = 0; j < vr[i].size(); j++)
    45                 if(can[vr[i][j]]==1) can[vr[i][j]] = -1;
    46         }
    47     }
    48     if(can[s]==0||can[s]==-1){
    49         cout<<"-1";
    50         return 0;
    51     }
    52     node p;
    53     p.num = s; p.step = 0;
    54     qq.push(p);
    55     used[s] = true;
    56 //    for(i = 1; i <= n; i++){
    57 //        if(can[i]) cout<<i<<" ";
    58 //    }
    59 //    cout<<endl;
    60     
    61     while(!qq.empty()){
    62         node k = qq.front();
    63         if(k.num==t){
    64             cout<<k.step;
    65             break;
    66         }
    67         qq.pop();
    68         for(i = 0; i < v[k.num].size(); i++){
    69             if(!used[v[k.num][i]]&&can[v[k.num][i]]!=0&&can[v[k.num][i]]!=-1){
    70                 p.num = v[k.num][i];
    71                 p.step = k.step+1;
    72                 qq.push(p);
    73                 used[p.num] = true;
    74             }
    75         }
    76     }
    77     return 0;
    78 }

    备注:

    两遍BFS。注意题目含义是,路径上所有点的所有出度都是可以到达终点的。因此不符合要求的点有两类,第一类是不能到达终点的点(用can[i]=0表示),第二类是直接指向不能到达终点的点(用can[i]=-1表示)。所以存一个反置图,首先从终点往回BFS,标记下能到达的点,再把不能到达的点所直接连接的点标记为-1。

    犯了两个错误,第一是,这两类点必须分开表示,如果在排查第二类点的时候也赋值为0,那么在往后接着找时,这个点会被视作第一类点,所以会删掉不应该删的点。第二,忘了写used[p.num]=true,即标黄那行,因为图中可能存在环,如果不进行判重就会超时。

  • 相关阅读:
    英语初级学习系列-00-Name-介绍自己
    Solidworks实例学习
    数学——泰勒公式
    SolidWorks知识积累系列-01
    彻底弄懂HTTP缓存机制及原理
    基于 Pymsql 数据库连接池
    WEB框架之Flask
    Django使用消息提示简单的弹出个对话框
    代码的调试、运行
    微信公众号本地测试环境搭建(附带内网穿透工具使用)
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/6078577.html
Copyright © 2020-2023  润新知