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

    问题 E: 寻找道路

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 61  解决: 9
    [提交] [状态] [讨论版] [命题人:admin]

    题目描述

    在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
    1 .路径上的所有点的出边所指向的点都直接或间接与终点连通。
    2 .在满足条件1 的情况下使路径最短。
    注意:图G 中可能存在重边和自环,题目保证终点没有出边。
    请你输出符合条件的路径的长度。

    输入

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

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

    0<n≤10,000,0<m≤200,000,0<x,y,s,t≤n,x≠t。

    输出

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

    样例输入

    3 2
    1 2
    2 1
    1 3
    

    样例输出

    -1
    

    提示

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

    Solution:记录一下每个点的出度,反向建边,再从终点bfs一遍,记录终点到每个点的路径条数,如果等于出度,则满足条件1,然后用这些符合条件1的点跑最短路即可。

    #include<bits/stdc++.h>
    #define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
    #define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
    #define PER(i, a, b) for(int i = (a); i >= (b); -- i)
    using namespace std;
    const int maxn=3e5+666;
    template <class T>
    inline void rd(T &ret){
        char c;
        ret = 0;
        while ((c = getchar()) < '0' || c > '9');
        while (c >= '0' && c <= '9'){
            ret = ret * 10 + (c - '0'), c = getchar();
        }
    }
    int head[maxn],vis[maxn],head1[maxn],vis1[maxn],ex[maxn],tot[maxn],l,r,s,t,dis[maxn];
    struct node{
          int u,v,nx;
    }p[maxn],q[maxn];
    int n,m;
    void addedge(int x,int y){
         p[++l].u=y,p[l].v=x,p[l].nx=head[y],head[y]=l;
         q[++r].u=x,q[r].v=y,q[r].nx=head1[x],head1[x]=r;
    }
    queue<int>qu;
    void bfs(){
        qu.push(t);
        vis[t]=1;
        while(qu.size()){
            int cur=qu.front();
            qu.pop();
            for(int i=head[cur];i;i=p[i].nx){
                int to=p[i].v;
                tot[to]++;
                if(!vis[to]){
                    qu.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    void spfa(){
         qu.push(s);
         REP(i,1,n)dis[i]=0x3f3f3f3f;
         dis[s]=0,vis1[s]=1;
         while(qu.size()){
              int cur=qu.front();
              qu.pop();
              vis1[cur]=0;
              for(int i=head1[cur];i;i=q[i].nx){
                   int to=q[i].v;
                   if(dis[to]>dis[cur]+1&&ex[to]==tot[to]){
                        dis[to]=dis[cur]+1;
                        if(!vis1[to]){
                            vis1[to]=1,qu.push(to);
                        }
                   }
              }
         }
    }
    int main(){
        rd(n),rd(m);
        REP(i,1,m){
           int a,b;
           rd(a),rd(b),ex[a]++;
           addedge(a,b);
        }
        rd(s),rd(t);
        bfs();
        spfa();
        if(dis[t]==0x3f3f3f3f)cout<<-1<<endl;
        else cout<<dis[t]<<endl;
        return 0;
    }
  • 相关阅读:
    二叉树【基础算法题】
    大话数据结构笔记——第五章 串
    大话数据结构笔记——第四章 栈与队列
    矩阵【基础算法题】
    大话数据结构笔记——第三章 线性表
    十大经典排序算法(Javascript版)
    比较器
    荷兰国旗问题
    好听的字
    mongodb 命令
  • 原文地址:https://www.cnblogs.com/czy-power/p/10412533.html
Copyright © 2011-2022 走看看