zoukankan      html  css  js  c++  java
  • Noip 2014 senior Day2 寻找道路(road)

    Noip 2014 senior Day2 寻找道路(road)

           【问题描述】

    在有向图 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】

    road.in                                                                                road.out

    3 2                                                                                        -1

    1 2

    2 1

    1 3

    【输入输出样例 2】

    6 6                                                                                           3

    1 2

    1 3

    2 6

    2 5

    4 5

    3 4

    1 5

    这道题的思路还是蛮好想的,我们找最短路径嘛,用什么SPFA啊,都好。我这里呢是选择建两个图(正向和反向),先使用DFS跑一遍反向图,将所能到达的点都标记一下,然后我们BFS从S到T搜索一下答案就好了。那么唯一需要注意的一点就是你在建立边集数组的时候注意变量名的区分(我就是这里爆掉了,我建图的时候是正向和反向一起建立的,但习惯性打Head,以至于反向图的建立爆掉了,而且破坏了正向图的储存)。

      

      1 //1.路径上的所有点的出边所指向的点都直接或间接与终点连通。
      2 //2.在满足条件1的情况下使路径最短。
      3 //3.图中可能存在重边和自环 
      4 #include<iostream>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<algorithm>
      8 #include<queue>
      9 #define N 10010
     10 #define M 200010
     11 using namespace std;
     12 
     13 inline long long read(){ 
     14     long long data=0,w=1; 
     15     char ch=0; 
     16     while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); 
     17     if(ch=='-') w=-1,ch=getchar(); 
     18     while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); 
     19     return data*w;
     20 }
     21 
     22 inline void write(long long x)
     23 {
     24      if(x<0) putchar('-'),x=-x;
     25      if(x>9) write(x/10);
     26      putchar(x%10+'0');
     27 }
     28 
     29 struct Edge{
     30     int startpoint,endpoint,next;
     31 }edge[M],invedge[M];
     32 
     33 int cnt,head[N],invhead[N];
     34 
     35 inline void addedge(int u,int v)
     36 {
     37     edge[++cnt].next = head[u];
     38     edge[cnt].startpoint = u;
     39     edge[cnt].endpoint = v;
     40     head[u] = cnt;
     41     invedge[cnt].next = invhead[v];
     42     invedge[cnt].startpoint = v;
     43     invedge[cnt].endpoint = u;
     44     invhead[v] = cnt;
     45 }
     46 
     47 int n,m,u,v;
     48 int The_start,The_end;
     49 bool visit[N],pass[N],flag_bfs[N];
     50 int ans[N];
     51 
     52 inline void dfs(int u)
     53 {
     54     for(int i=invhead[u];i;i=invedge[i].next)
     55     {
     56         if(!visit[invedge[i].endpoint])
     57         {
     58             visit[invedge[i].endpoint] = true;
     59             dfs(invedge[i].endpoint);
     60         }
     61     }
     62 }
     63 
     64 //int que[N * 10];
     65 
     66 inline void bfs(int u) //这里注释的是我以为我用队列用错了 
     67 {
     68     queue <int> que;
     69     que.push(u);
     70     
     71 //    int head_bfs = 0,tail_bfs = 1;
     72 //    que[tail_bfs] = u;
     73     
     74     flag_bfs[u] = true;
     75     while(!que.empty() /*head_bfs < tail_bfs*/)
     76     {
     77         int aider = que.front() /*que[++head_bfs]*/;
     78         que.pop();
     79         if(aider == The_end) break;
     80         for(int i=head[aider];i;i=edge[i].next)
     81         {
     82             if(pass[edge[i].endpoint] && !flag_bfs[edge[i].endpoint])
     83             {
     84                 que.push(edge[i].endpoint);
     85 //                que[++tail_bfs] = edge[i].endpoint;
     86                 ans[edge[i].endpoint] = ans[aider] + 1;
     87                 flag_bfs[edge[i].endpoint] = true;
     88             }
     89         }
     90     }
     91 }
     92 
     93 int main()
     94 {
     95     freopen("road.in","r",stdin);
     96     freopen("road.out","w",stdout);
     97     
     98     n = read();
     99     m = read();
    100     for(int i=1;i<=m;i++)
    101     {
    102         u = read();
    103         v = read();
    104         addedge(u,v);
    105     }
    106     The_start = read();
    107     The_end = read();
    108     visit[The_end] = true;
    109     dfs(The_end);
    110     for(int i=1;i<=n;i++)
    111     {
    112         bool flag = true;
    113         for(int j=head[i];j;j=edge[j].next)
    114         {
    115             if(!visit[edge[j].endpoint])
    116             {
    117                 flag = false;
    118                 break;
    119             }
    120         }
    121         if(flag) pass[i] = true;
    122     }
    123     bfs(The_start);
    124     if(ans[The_end] == 0) write(-1);
    125     else write(ans[The_end]);
    126         
    127     return 0;
    128 }
  • 相关阅读:
    每周总结8.18
    每周总结7.28
    每周总结8.25
    每周总结7.21
    每周总结8.11
    每周总结8.4
    大道至简 读后感
    递归进行回文的判断
    课后作业1
    GoodBlogs Websites
  • 原文地址:https://www.cnblogs.com/sin-mo/p/7191809.html
Copyright © 2011-2022 走看看