码迷,mamicode.com
首页 > 其他好文 > 详细

[NOIP2014] 寻找道路

时间:2017-08-01 09:18:06      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:printf   front   algorithm   else   div   scan   put   包含   存在   

题目描述

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

 

题解:

反着bfs一遍,再正着跑一遍spfa

不知道为什么水过了......

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 using namespace std;
 9 
10 const int maxn = 10010;
11 const int maxm = 200010;
12 
13 int n,m,s,t,inf,dis[maxn];
14 int nxt[maxm],to[maxm],h[maxn],e_num;
15 int nxt1[maxm],to1[maxm],h1[maxn],e_num1;
16 bool vis[maxn],bj[maxn],in[maxn];
17 
18 queue<int> q;
19 
20 void add(int x, int y) {
21   nxt[++e_num]=h[x],to[e_num]=y,h[x]=e_num;
22   nxt1[++e_num1]=h1[y],to1[e_num1]=x,h1[y]=e_num1;
23 }
24 
25 void bfs() {
26   q.push(t),vis[t]=1;
27   while(!q.empty()) {
28     int u=q.front(); q.pop();
29     for(int i=h1[u]; i; i=nxt1[i]) {
30       int v=to1[i];
31       if(vis[v]) continue;
32       vis[v]=1,q.push(v);
33     }
34   }
35 }
36 
37 void spfa() {
38   memset(dis,127/3,sizeof(dis)),inf=dis[0];
39   dis[s]=0,in[s]=1,q.push(s);
40   while(!q.empty()) {
41     int u=q.front();
42     in[u]=0,q.pop();
43     for(int i=h[u]; i; i=nxt[i]) {
44       int v=to[i];
45       if(dis[u]+1<dis[v] && !bj[v]) {
46     dis[v]=dis[u]+1;
47     if(!in[v]) in[v]=1,q.push(v);
48       }
49     }
50   }
51 }
52 
53 int main() {
54   scanf("%d%d", &n, &m);
55   for(int i=1; i<=m; i++) {
56     int x,y;
57     scanf("%d%d", &x, &y);
58     add(x,y);
59   }
60   scanf("%d%d", &s, &t);
61   bfs();
62   for(int u=1; u<=n; u++) {
63     if(!vis[u]) {
64       for(int i=h1[u]; i; i=nxt1[i]) {
65     int v=to1[i];
66     bj[v]=1;
67       }
68     }
69   }
70   spfa();
71   if(dis[t]==inf) puts("-1");
72   else printf("%d", dis[t]);
73   return 0;
74 }

 

[NOIP2014] 寻找道路

标签:printf   front   algorithm   else   div   scan   put   包含   存在   

原文地址:http://www.cnblogs.com/HLXZZ/p/7266634.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!