【NOIP之旅】NOIP2014 day2 T2 寻找道路

2.寻找道路

(road.cpp/c/pas)

【问题述】

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

2 1

1 3


-1

【输入输出样例说明】

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

【输入输出样例2】


road.in


road.out


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计算最短路。

但重边自环以及数据nm着实有些坑,刚开始用的是vector G[]记录出边+vector edges记录边,但是nm直接就超内存了。学了别人的一种方法:对于结点的边建立一个链表,e[]记录边,first[]是表头,Edge 中的next域为指向下一条边的指针。很实用的方法。

另外用到了一个技巧,正反向边依顺序加入,根据标号判断是正向还是反向,只用一个BFS完成操作。

教训:提前就应该分析数据考虑怎样存储,不能想当然。

【代码】

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define REP(a,b,c) for(int a=(b);a<=(c);a++)
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
//注意如果REP(i,0,G[u].size()-1)会出BUG
//vector G[u]表示出边 不能用 n<=200000如果一个出边特别大的话就会超内存
//利用边的加入顺序达到记录反向边的效果
using namespace std;

const int maxn = 600000;

struct Edge{
  int u,v,next;
}edges[maxn];
int en=0;
int first[maxn];
//存图方法: edges存正反向边 edges.size()==en firts[u]是邻接表的首
//邻接表中存储相连边 

int d[maxn];
int vis[maxn];
int n,m,s,t;

void add(int u,int v){
    en++;
    edges[en].u=u; edges[en].v=v;
    edges[en].next=first[u];
    first[u]=en;
}

void bfs(int s,int flag) { //flag标志正反向
    memset(d,-1,sizeof(d));
    queue<int> q; q.push(s);d[s]=0;
    //vis[s]不要标记否则第一次把t标记正向不能访问
    while(!q.empty()) {
        int u=q.front(); q.pop();
          for(int j=first[u];j>0;j=edges[j].next) if(j%2==flag && !vis[edges[j].v]) {
              int v=edges[j].v;
              if(d[v] == -1){  //d==-1 的判断
                 d[v]=d[u]+1;
                 q.push(v);
              }
          }
    }
    return ;
}

int main() {
    memset(first,-1,sizeof(first));
    scanf("%d%d",&n,&m);
    REP(i,1,m) {
        int u,v; scanf("%d%d",&u,&v);
        add(u,v);  //正反向添加两条边 关系为相 ^
        add(v,u);
    }
    scanf("%d%d",&s,&t);

    bfs(t,0);  //%==0为反向边
    for(int j=1;j<=2*m;j+=2) if(d[edges[j].v]==-1)  //由can推vis 而不能直接在can上操作
    //注意只枚举正向边
      vis[edges[j].v]=vis[edges[j].u]=1;

    bfs(s,1);
    printf("%d",d[t]);
    return 0;
}
时间: 2024-10-10 05:50:29

【NOIP之旅】NOIP2014 day2 T2 寻找道路的相关文章

NOIP 2014 Day2 T2 寻找道路

1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<queue> 5 #include<stack> 6 #include<vector> 7 #include<algorithm> 8 #include<string> 9 #include<cstring> 10 #include<iomanip>

【DFS】【最短路】【spfa】【BFS】洛谷P2296 NOIP2014提高组 day2 T2 寻找道路

存反图,从终点dfs一遍,记录下无法到达的点. 然后枚举这些记录的点,把他们的出边所连的点也全部记录. 以上这些点都是无法在最短路中出现的. 所以把两个端点都没被记录的边加进图里,跑spfa.BFS什么的随意. 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 #define N 10001 7 vector

【DFS】【图论】NOIP2014寻找道路

[NOIP2014]寻找道路 题目描述 Description 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1.路径上的所有点的出边所指向的点都直接或间接与终点连通. 2.在满足条件1的情况下使路径最短. 注意:图G中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入描述 Input Description 第一行有两个用一个空格隔开的整数n和m,表示图有n个点和m条边. 接下来的m行每行2个整数x.

[FZYZOJ 2047] [NOIP2014 D2T2] 寻找道路

[NOIP2014_D2_T2]寻找道路 时间限制:1000MS 内存限制:131072KB Description 在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1.路径上的所有点的出边所指向的点都直接或间接与终点连通. 2.在满足条件 1 的情况下使路径最短. 注意:图 G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. Input Format 第一行有两个用一个空格隔开的整数 n 和 m,

寻找道路——呆滞大佬der最骚暴力

寻找道路 题目描述: 有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条件1 的情况下使路径最短. 注意:图G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入格式: 第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边. 接下来的m 行每行2 个整数x .y ,之间用一个空格隔开,表示有一条边从点x 指向点y . 最后一行有两个用一个空格隔开的整数s .t ,表示起点为s ,终点为t . 输出格式: 输出只有一行,包含一个整数,表示

[UOJ] #19 寻找道路

#19. 寻找道路NOIP2014 在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 路径上的所有点的出边所指向的点都直接或间接与终点连通. 在满足条件 1 的情况下使路径最短. 注意:图 GG 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入格式 第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边. 接下来的 mm 行每行 22 个整数 x,yx,y,之间用

P2296 寻找道路

P2296 寻找道路 题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条件1 的情况下使路径最短. 注意:图G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入输出格式 输入格式: 输入文件名为road .in. 第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边. 接下来的m 行每行2 个整数

【BZOJ 4517】【SDOI 2016】Round1 Day2 T2 排列计数

本蒟蒻第一次没看题解A的题竟然是省选$Round1$ $Day2$ $T2$ 这道组合数学题. 考试时一开始以为是莫队,后来想到自己不会组合数的一些公式,便弃疗了去做第三题,,, 做完第三题后再回来看这道题,想到暴力算$组合数×错排$,我记得有一天晚上$Snayvals$问过我错排公式怎么推,但我并没有在意!!!幸亏我知道错排可以线性推出来,便开始用笔推错排公式.推了$30min$发现有计算机为什么不用!!!便打了一个表,很快就找出了规律$f[i]=(f[i-1]*f[i-2])*(i-1)$

洛谷P2296 寻找道路==codevs3731 寻找道路

P2296 寻找道路 题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条件1 的情况下使路径最短. 注意:图G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入输出格式 输入格式: 输入文件名为road .in. 第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边. 接下来的m 行每行2 个整数