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

    题目描述

    在有向图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:
    3 2  
    1 2  
    2 1  
    1 3  
    
    输出样例#1:
    -1
    输入样例#2:
    6 6  
    1 2  
    1 3  
    2 6  
    2 5  
    4 5  
    3 4  
    1 5  
    
    输出样例#2:
    3

    说明

    解释1:

    如上图所示,箭头表示有向道路,圆点表示城市。起点1 与终点3 不连通,所以满足题

    目᧿述的路径不存在,故输出- 1 。

    解释2:

    如上图所示,满足条件的路径为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。

    思路:

    这题乍一看就是个最短路,但实际上有一个条件是不可忽略的“路径上的所有点的出边所指向的点都直接或间接与终点连通”,为了满足这个条件,需要把这个有向图逆向存储一遍,把经过的点标记下来,没有经过的点自然不符合要求,但这时问题来了,像图二中的情况,很明显我们会把点6忽略掉,但其实点2也应该被忽略,这就需要我们把能与这个点直接相通的所有点忽略。

    当剩下的点都是有效点时,就可以用求最短路的方法把答案求出,我个人认为广搜比较方便,当然也可以用spfa

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdio>
     6 #include<vector>
     7 using namespace std;
     8 int x,y,s,t,n,m,h[10001],f[10001],tr;
     9 vector<int>a[10002],b[10002];//用来制作两个临接链表,一个正向一个反向
    10 void dfs(int u)
    11 {
    12     if(h[u])return;//避免环状道路导致的死循环 
    13     f[u]=1;h[u]=1;//h[]判断是否访问过这个点,f[]判断该点是否可行 
    14     for(int i=0;i<b[u].size();i++)
    15       dfs(b[u][i]);
    16  } 
    17 void bfs(int u)
    18 {
    19     int g[10002],ans[10002],l=0,fl[10002],xx;
    20     memset(fl,0,sizeof(fl));
    21     memset(ans,0,sizeof(ans));
    22     for(int i=0;i<a[u].size();i++)
    23         if(!fl[a[u][i]]&&f[a[u][i]])
    24         {ans[l]=1;g[l++]=a[u][i];fl[a[u][i]]=1;}
    25     for(int i=0;i<l;i++)
    26     {
    27         if(g[i]==t){tr=1;cout<<ans[i];break;}
    28         xx=g[i];
    29         for(int j=0;j<a[xx].size();j++)
    30           if(!fl[a[xx][j]]&&f[a[xx][j]])
    31           {ans[l]=ans[i]+1;g[l++]=a[xx][j];fl[a[xx][j]]=1;}
    32     }
    33 }
    34 int main()
    35 {
    36     cin>>n>>m;
    37     for(int i=0;i<m;i++)
    38     {
    39         cin>>x>>y;
    40         a[x].push_back(y);//正向存储 
    41         b[y].push_back(x);//逆向存储 
    42     }
    43     cin>>s>>t;
    44     dfs(t);
    45     memset(h,0,sizeof(h));
    46     for(int i=1;i<=n;i++)
    47     {
    48         if(!f[i])continue;//忽视这个点,相当于把它从图里删除了 
    49         for(int j=0;j<a[i].size();j++)
    50             if(!f[a[i][j]]){h[i]=1;break;}
    51     }
    52     for(int i=1;i<=n;i++)
    53       if(h[i])f[i]=0;//把连向“被忽视的点”的点忽视
    54     if(f[s])bfs(s);
    55     if(!tr)cout<<-1;
    56     return 0; 
    57 }
  • 相关阅读:
    poj 3528 (三维几何求凸包+凸包表面积)
    dijkstra模板(好像是斐波那契额堆优化,但我为什么看起来像优先队列优化,和spfa一样)
    最大空凸包模板
    ICPC 2017–2018, NEERC, Northern Subregional Contest St Petersburg, November 4, 2017 I题
    hdu 5248 序列变换
    hdu 2063(二分图模板测试)
    组合数
    85. Maximal Rectangle 由1拼出的最大矩形
    750. Number Of Corner Rectangles四周是点的矩形个数
    801. Minimum Swaps To Make Sequences Increasing 为使两个数组严格递增,所需要的最小交换次数
  • 原文地址:https://www.cnblogs.com/thmyl/p/7359407.html
Copyright © 2011-2022 走看看