1807. [NOIP2014]寻找道路P2296 寻找道路
2018-06-17 22:30:07来源:未知 阅读 ()
题目描述
在有向图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 。
输入输出样例
3 2 1 2 2 1 1 3
-1
6 6 1 2 1 3 2 6 2 5 4 5 3 4 1 5
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 int to=edge[i].v;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #define INF 0x7ffffff 7 using namespace std; 8 int read(int & n) 9 { 10 int flag=0,x=0;char c='/'; 11 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;} 12 while(c>='0'&&c<='9')x=x*10+(c-48),c=getchar(); 13 if(flag)n=-x;else n=x; 14 } 15 const int MAXN=200001; 16 int n,m,bgx,bgy; 17 int rudu[MAXN]; 18 struct node 19 { 20 int u,v,w,nxt; 21 }edge[MAXN]; 22 int num=1; 23 int head[MAXN]; 24 int flag[MAXN];// 记录每个值是否能够到达终点 25 int cs[MAXN]; 26 int dis[MAXN]; 27 int vis[MAXN]; 28 void add_edge(int ll,int rr,int ww) 29 { 30 edge[num].u=ll; 31 edge[num].v=rr; 32 edge[num].w=ww; 33 edge[num].nxt=head[ll]; 34 head[ll]=num++; 35 } 36 void bfs() 37 { 38 queue<int>q; 39 int tot=0; 40 q.push(bgx),tot++; 41 while(q.size()!=0) 42 { 43 int p=q.front(); 44 q.pop(); 45 for(int i=head[p];i!=-1;i=edge[i].nxt) 46 { 47 int to=edge[i].v; 48 if(cs[to]++)continue; 49 q.push(to); 50 } 51 } 52 //rudu[bgy]=0; 53 for(int i=1;i<=n;i++) 54 if(rudu[i]!=cs[i]&&i!=bgy) 55 flag[i]=1; 56 } 57 void dele() 58 { 59 for(int i=1;i<=num;i++) 60 { 61 if(flag[edge[i].u]!=0) 62 { 63 edge[i].u=-1; 64 edge[i].v=-1; 65 edge[i].w=-1; 66 edge[i].nxt=-1; 67 } 68 } 69 } 70 void spfa() 71 { 72 queue<int>q; 73 q.push(bgx); 74 dis[bgx]=0; 75 while(q.size()!=0) 76 { 77 int p=q.front(); 78 q.pop(); 79 vis[p]=0; 80 for(int i=head[p];i!=-1;i=edge[i].nxt) 81 { 82 if(edge[i].u==-1)continue; 83 int to=edge[i].v; 84 if(dis[to]>dis[p]+edge[i].w) 85 { 86 dis[to]=dis[p]+edge[i].w; 87 if(vis[to]==0) 88 { 89 vis[to]=1; 90 q.push(to); 91 } 92 } 93 } 94 } 95 if(dis[bgy]==INF) 96 printf("-1"); 97 else 98 printf("%d",dis[bgy]); 99 } 100 int main() 101 { 102 freopen("roadb.in","r",stdin); 103 freopen("roadb.out","w",stdout); 104 read(n);read(m); 105 for(int i=1;i<=n;i++)head[i]=-1,dis[i]=INF; 106 for(int i=1;i<=m;i++) 107 { 108 int x,y; 109 read(x);read(y); 110 add_edge(y,x,1); 111 rudu[x]++; 112 } 113 read(bgy);read(bgx); 114 bfs(); 115 dele(); 116 spfa(); 117 return 0; 118 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 寻找两个有序数组的中位数 2020-04-09
- [NOIP2014]解方程 2018-06-17
- NOYJ——寻找最大数 2018-06-17
- 二分搜索 2018-06-17
- Luogu 2296 寻找道路 2018-06-17
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash