【NOIP2014提高组T5】寻找道路-双spfa
2016-07-19 19:07
381 查看
(本人本题完成于2016-7-19)
题目大意:给一个有向图,每条边的权值为1,求是否存在一条从点s到点t的路径使得路径上的每一个点的出边所指的点都存在到t的路径,如果有,输出最短路径长度,否则输出-1。
做法:由于点数N很大(可达10000),所以要用邻接表存储有向图。在读入边时,顺便存一个反图,对该反图以t为起点做一遍spfa,找到不存在到t的路径的点(即在反图中由t不能到达的点),再将这些点和反图中这些点所指向的点(即正图中有出边指向这些点的点)标记上,再对正图以s为起点做一遍spfa,避开标记过的点(即不能在路径中出现的点),就能得出答案了。
以下是本人代码:
题目大意:给一个有向图,每条边的权值为1,求是否存在一条从点s到点t的路径使得路径上的每一个点的出边所指的点都存在到t的路径,如果有,输出最短路径长度,否则输出-1。
做法:由于点数N很大(可达10000),所以要用邻接表存储有向图。在读入边时,顺便存一个反图,对该反图以t为起点做一遍spfa,找到不存在到t的路径的点(即在反图中由t不能到达的点),再将这些点和反图中这些点所指向的点(即正图中有出边指向这些点的点)标记上,再对正图以s为起点做一遍spfa,避开标记过的点(即不能在路径中出现的点),就能得出答案了。
以下是本人代码:
#include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #define inf 99999999 using namespace std; int n,m,s,t,total=0,last[10010]={0},flast[10010]={0}; bool vi[10010]={0}; struct edge { long v,next; }g[220010],fg[220010]; //数组模拟链表,用邻接表存储有向图,g为正图,fg为反图 void readg(int i,int j) //往正图中加入边(i,j) { g[last[i]].next=total; g[total].v=j; g[total].next=0; last[i]=total; } void readfg(int i,int j) //往反图中加入边(i,j) { fg[flast[i]].next=total; fg[total].v=j; fg[total].next=0; flast[i]=total; } void input() { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { last[i]=i; flast[i]=i; g[i].next=0;g[i].v=i; fg[i].next=0;fg[i].v=i; total++; } for(int i=1;i<=m;i++) { int x,y; scanf("%d %d",&x,&y); total++; readg(x,y); readfg(y,x); } scanf("%d %d",&s,&t); } void fspfa() { bool d[10010]={0}; queue <int> q; q.push(t);d[t]=1; while(!q.empty()) { int h=q.front(),i; q.pop(); i=h; while(i!=0) { if (!d[fg[i].v]) {q.push(fg[i].v);d[fg[i].v]=1;} //如果该点没访问过,将其插入队列 i=fg[i].next; } } for(int i=1;i<=n;i++) //标记路径中不能包含的点 if (!d[i]) { int j=i; while(j!=0) { vi[fg[j].v]=1; j=fg[j].next; } } } void spfa() { int d[10010]; queue <int> q; q.push(s);d[s]=0; if (vi[s]) {printf("-1");return;} for(int i=1;i<=n;i++) if (i!=s) d[i]=inf; while(!q.empty()) { int h=q.front(),i; q.pop(); i=h; while(i!=0) { if (!vi[g[i].v]&&d[h]+1<d[g[i].v]) {q.push(g[i].v);d[g[i].v]=d[h]+1;} //做spfa时避开不能包含的点 i=g[i].next; } } if (d[t]!=inf) printf("%d",d[t]); else printf("-1"); } int main() { input(); fspfa(); spfa(); return 0; }
相关文章推荐
- 迪米特法则详解--七大面向对象设计原则(6)
- 今天所讲的内容以及已制作完成的游戏
- dp 硬币找零问题
- Ubuntu 系统引导(grub)修复
- C# winform使用log4net步骤
- php设计模式学习之工厂模式
- Maven在Eclipse中的实用小技巧
- Mouseenter/ mouseleave和mouseover/mouseout
- 设计模式-桥接模式
- 协议简介之 应用层协议
- Codeforces Round #312 (Div. 2) - C. Amr and Chemistry
- web前端响应式
- 【NLP】蓦然回首:谈谈学习模型的评估系列文章(三)
- position:static | relative | absolute | fixed
- 语言国际化自适应
- 这是一个新的开始
- caffe的python接口学习(6):用训练好的模型(caffemodel)来分类新的图片
- UVA 10494 If We Were a Child Again
- Docker 系列之 Linux 下安装篇
- android中的文件操作详解以及内部存储和外部存储