【NOIP2014】D2T2 寻找道路
2016-07-29 18:50
381 查看
在有向图 GG 中,每条边的长度均为 11,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 的情况下使路径最短。
注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。
接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。
最后一行有两个用一个空格隔开的整数 s,ts,t,表示起点为 ss,终点为 tt。
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出−1
−1
思路
先从终点反向DFS一遍,求出能走的点,然后一遍SPFA轻松带走
复杂度:反正可以AC,一般是先想办法过掉部分分然后才去看复杂度AC不AC,否则再优化
代码修修补补,可能会比较长,但是非常好懂
路径上的所有点的出边所指向的点都直接或间接与终点连通。
在满足条件 1 的情况下使路径最短。
注意:图 GG 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入格式
第一行有两个用一个空格隔开的整数 nn 和 mm,表示图有 nn 个点和 mm 条边。接下来的 mm 行每行 22 个整数 x,yx,y,之间用一个空格隔开,表示有一条边从点 xx 指向点yy。
最后一行有两个用一个空格隔开的整数 s,ts,t,表示起点为 ss,终点为 tt。
输出格式
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出−1−1
思路
先从终点反向DFS一遍,求出能走的点,然后一遍SPFA轻松带走
复杂度:反正可以AC,一般是先想办法过掉部分分然后才去看复杂度AC不AC,否则再优化
代码修修补补,可能会比较长,但是非常好懂
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<limits.h> #include<algorithm> #include<vector> using namespace std; const int maxn=10005; vector<int> g[maxn];//反向路径存储的邻接表 vector<int> p[maxn];//正向的 int d[maxn]; queue<int> q; bool book[maxn];//用于spfa int n,m; int t1,t2; int st,ed; bool e[maxn][maxn];//避免重边再存个邻接矩阵 bool In[maxn];//第一次染色看能否走的数组 bool in2[maxn];//using inv 1 for not in染色的时候辅助用 void dfs(int x)//搜索的时候记得记忆化啊,人家没有保证没有环~ { if(In[x])return; In[x]=1; int lm=g[x].size(); for(int i=0;i<lm;i++) { if(!In[g[x][i]]) dfs(g[x][i]); } } void git(int &xxx)//读入优化,也很好懂 { //&之后的东西就可以直接用了 char ch=getchar(); xxx=0; while(ch<'0'||ch>'9') ch=getchar();//过滤字符 while(ch>='0'&&ch<='9') { xxx=xxx*10+ch-'0'; ch=getchar(); } //逐位累加 } const int inf=INT_MAX; //最大值,用INT_MAX也可以 int main() { scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) { git(t1);git(t2); if(e[t1][t2]) continue; if(t1==t2) continue;//这个用来避免自环 e[t1][t2]=1; p[t1].push_back(t2);//正向 g[t2].push_back(t1);//反向 } scanf("%d %d",&st,&ed); dfs(ed); //首次染色完成,找到了那些不能到达终点的点 //下面是第二次染色,用来把那些指向不能到达的定点的点也染上了色,为了避免先刷成1,这次用1表示不可以走 for(int i=1;i<=n;i++) { if(in2[i]) continue; if(!In[i]) { in2[i]=1; int lm=g[i].size(); for(int j=0;j<lm;j++) { in2[g[i][j]]=1; } } } if(in2[st]) { cout<<-1<<endl; return 0; } //如果不能起点不能到达,那么-1拜拜return for(int i=0;i<=n;i++) d[i]=inf; //spfa第一步,先刷成无限大int_max表示最大值,是大写,很清真 book[st]=1; d[st]=0; q.push(st);//开始的时候起点入队 while(!q.empty()) { int nw=q.front(); int lm=p[nw].size(); for(int i=0;i<lm;i++) { int u=p[nw][i]; if(in2[u]) continue;//不能走的话就continue啦 if(d[u]>d[nw]+1) { d[u]=d[nw]+1; if(!book[u]) { book[u]=1; q.push(u); }//如果这个边可以松弛的话就松弛然后入队 } } book[nw]=0; q.pop();//注意入队时book在队中标记为1,出队的时候就还原为0 } if(d[ed]==inf) { cout<<-1<<endl; return 0; //如果还是int_max的话就没走到嘛 //int_max比答案大好多嘛 } else cout<<d[ed]<<endl; return 0; }
相关文章推荐
- 安装mysql的问题总结
- HDU 3530 Subsequence(区间最值差>=m且<=k的最大长度、双单调队列)
- 自定义收缩TextView
- C# 常见错误处理
- WKWebView与Js实战(OC版)
- Codeforces 161A Dress'em in Vests!
- await and async
- Python多进程编程
- Android笔记 week3.1之"自定义控件"
- 加密会话(SSL)Cookie 中缺少 Secure 属性
- Django集成已有的数据库和应用
- 生命周期
- Android Studio 引用和生成aar
- POJ1050 To the Max
- lnmp_for_shop123_latest.tar.gz光年服务器 环境 安装
- 利用bash自动化重复操作
- SQL学习笔记(1)
- 关于没有登录wifi的网络连接问题
- 在mac上搭建python环境
- LVS+Keepalived实现高可用集群