原题链接:蓝桥杯2013年第四届真题-危险系数
解题思路:根据题意,如果某一点为”关键点“,那么所有路径中都会出现它。所以可以设置一个time数组表示某一点被访问的次数,如果正好等于路径数,那么它就是”关键点“。寻找路径可以使用DFS。
我们可以用链式向前星存储图,以达到省空间的目的,同时也能在一定程度上节省时间。
有关链式向前星的讲解,请点击这里。
注意事项:
我当时犯了2个错误:
1.dfs函数一开始就无条件tme[cur]++;实际上cur能不能到目的地还不一定呢;
2.把cnt+=dfs(to,e)弄成if(dfs(to,e)) cnt++;个人认为,这样做其实是在求某点邻接边中能到达目标节点的总数。比如下面的图,大家可以模拟一下(那堆带箭头的是递归过程)
还有注意起点和终点不要算进去。
参考代码:
#include<cstdio> #include<algorithm> #include<vector> const int M=1002,M_EDGE=2001; using namespace std; struct graph { int next,to; graph():next(-1),to(-1) {} graph(int n,int t):next(n),to(t) {} }; vector<graph> G; int n,fir[M],tme[M],cnt=0; bool vis[M]; //构建边 void add(int u,int v,int &m) { G[m]=graph(fir[u],v); fir[u]=m++; } int dfs(int cur,int e) { if(cur==e) { cnt++; return 1; } //cnt:经过当前节点的路径数 int cnt=0; for(int i=fir[cur]; i!=-1; i=G[i].next) { int to=G[i].to; if(!vis[to]) { vis[to]=1; cnt+=dfs(to,e); vis[to]=0; } } tme[cur]+=cnt; return cnt; } int main() { int m,t=0,res=0; scanf("%d%d",&n,&m); fill(fir+1,fir+n+1,-1); //以下为初始化 G.resize(min(m*(m-1),M_EDGE)); for(int i=0; i<m; i++) { int u,v; scanf("%d%d",&u,&v); add(u,v,t); add(v,u,t); } int s,e; scanf("%d%d",&s,&e); vis[s]=1; dfs(s,e); if(cnt==0) printf("-1"); else { for(int i=1; i<=n; i++) { if(tme[i]==cnt&&i!=s&&i!=e) { //printf("%d ",i); res++; } } } printf("%d",res); return 0; }
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复