历届试题 网络寻路
来源:互联网 发布:淘宝活动策划方案 编辑:程序博客网 时间:2024/06/09 16:24
问题描述
X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如下图所示的网络。
1 -> 2 -> 3 -> 1 是允许的
1 -> 2 -> 1 -> 2 或者 1 -> 2 -> 3 -> 2 都是非法的。
输入格式
输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
输出格式
输出一个整数,表示满足要求的路径条数。
样例输入1
3 3
1 2
2 3
1 3
样例输出1
6
样例输入2
4 4
1 2
2 3
3 1
1 4
样例输出2
10
这是一道看起来十分简单的题目。
只要进行深搜就可以了,可是却让我发现了我之前一直没发现的自己编程上面常常犯的错误。就是想当然,不分实际情况,例如
在深搜回溯的时候 我一般想当然 在DFS之前vis=1在这之后vis=0;然而这道题目却告诉我不能随便改变DFS的初始状态
比如说下面的代码 我怎么也想不到会错
#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<set>#include<queue>#include<vector>using namespace std;const int maxn=10100;int n,m;int u,v;vector<int>G[maxn];int vis[maxn]={0};int ans=0;vector<int>path;void dfs(int s,int x,int in){if(in==3){ans++;for(int i=0;i<path.size();i++)cout<<path[i]<<" ";cout<<endl;return;}else{for(int i=0;i<G[x].size();i++){int v=G[x][i];if(vis[v]==0||(in==2&&v==s)){vis[v]=1;//错就错在这里啊path.push_back(v); dfs(s,v,in+1); path.pop_back();vis[v]=0;//这里如果第四个结点放的是和第一个结点一样数,vis就把这个结点的状态变了 导致下一轮的时候错了,可以把v 改成x }}} }int main(){ freopen("d://jin.txt","r",stdin); cin>>n>>m; while(m--){ cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++){vis[i]=1;path.push_back(i); dfs(i,i,0); path.pop_back(); vis[i]=0; } cout<<ans; return 0;}再比如说下面的代码 导致的就是比答案少了
#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<set>#include<queue>#include<vector>using namespace std;const int maxn=10100;int n,m;int u,v;vector<int>G[maxn];int vis[maxn]={0};int ans=0;vector<int>path;void dfs(int s,int x,int in){vis[x]=1;//原本以为在dfs外面改变vis和里面是一样的,没想到啊if(in==3){ans++;for(int i=0;i<path.size();i++)cout<<path[i]<<" ";cout<<endl;return;}//错在这里 提前return了状态都没变回来啊else{for(int i=0;i<G[x].size();i++){int v=G[x][i];if(vis[v]==0||(in==2&&v==s)){path.push_back(v); dfs(s,v,in+1); path.pop_back(); }}} vis[x]=0;}int main(){ freopen("d://jin.txt","r",stdin); cin>>n>>m; while(m--){ cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++){path.push_back(i); dfs(i,i,0); path.pop_back();//还是应该在这种地方先搞vis 因为这也是在一个循环里面的 } cout<<ans; return 0;}
下面是一种正确的方法
#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<set>#include<queue>#include<vector>using namespace std;const int maxn=10100;int n,m;int u,v;vector<int>G[maxn];int vis[maxn]={0};int ans=0;vector<int>path;void dfs(int s,int x,int in){if(in==3){ans++;for(int i=0;i<path.size();i++)cout<<path[i]<<" ";cout<<endl;return;}else{for(int i=0;i<G[x].size();i++){int v=G[x][i];if(vis[v]==0||(in==2&&v==s)){if(v!=s)vis[v]=1;path.push_back(v); dfs(s,v,in+1); path.pop_back();if(v!=s)vis[v]=0; }}} }int main(){ freopen("d://jin.txt","r",stdin); cin>>n>>m; while(m--){ cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++){vis[i]=1;path.push_back(i); dfs(i,i,0); path.pop_back();vis[i]=0; } cout<<ans; return 0;}
所谓回溯,就是回到初始的状态
阅读全文
0 0
- 历届试题 网络寻路
- 历届试题 网络寻路
- 历届试题 网络寻路
- 历届试题 网络寻路
- 历届试题 网络寻路
- 历届试题 网络寻路
- 蓝桥杯 历届试题 网络寻路
- 历届试题 网络寻路 (树上dfs)
- 历届试题 网络寻路 dfs
- 历届试题 网络寻路 蓝桥杯
- 蓝桥 历届试题 网络寻路
- 历届试题网络寻路(dfs)
- 蓝桥杯-历届试题-PREV-13-网络寻路
- 蓝桥杯 历届试题 网络寻路 (dfs)
- 蓝桥杯 历届试题 网络寻路(暴力 dfs)
- 历届试题 错误票据
- 历届试题 剪格子
- 历届试题 错误票据
- java对cookie的操作
- Android 热更新之tinker
- 简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别
- tftp的使用
- js在html页面中的引用位置思考
- 历届试题 网络寻路
- spliterators
- postgreSQL 用户、角色、权限、数据库的简单使用
- 【网络优化】超轻量级网络SqueezeNet算法详解
- 1.MYSQL & InnoDB体系结构
- Properties文件载入工具类
- java WebService简单教程
- Android线程—主要方法
- extjs grid的列表示金额的数字显示为千分位