历届试题 网络寻路
问题描述
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 2
2 3
1 3
样例输出1
6
样例输入2
4 4
1 2
2 3
3 1
1 4
1 2
2 3
3 1
1 4
样例输出2
10
思路:暴力dfs加剪枝。依次从每个节点出发,找到一个长度为四的路径,可以为环,保证第一个节点不可以和第二个第三个节点相同,第四个节点不可以和第三个节点的和第二个节点相同
代码1如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int Amap[5001][5001]; 4 int array[4]; 5 int start; 6 int end; 7 int sum=0; 8 int t=1; 9 int N,M; 10 void dfs(int n) 11 { 12 if(t==3){ 13 for(int i=1;i<=N;i++){ 14 if(Amap[n][i]==1){ 15 sum++; 16 } 17 } 18 sum--; 19 }else{ 20 for(int i=1;i<=N;i++){ 21 if(Amap[n][i]==1){ 22 array[t]=i; 23 if(t==1){ 24 t++; 25 dfs(i); 26 t--; 27 } 28 if(t==2){ 29 t++; 30 if(array[0]!=array[2]){ 31 dfs(i); 32 } 33 t--; 34 } 35 36 } 37 } 38 } 39 } 40 int main() 41 { 42 memset(Amap,0,sizeof(Amap)); 43 memset(array,0,sizeof(array)); 44 45 cin >> N>> M; 46 for(int i=0;i<M;i++){ 47 cin >> start >> end; 48 Amap[start][end]=Amap[end][start]=1; 49 } 50 for(int i=1;i<=N;i++){ 51 array[0]=i; 52 dfs(i); 53 } 54 cout << sum; 55 return 0; 56 }
由于第五组测试数据过大,数组不可以分那么多的空间,考虑使用vector代码如下:
代码2:
1 #include<bits/stdc++.h> 2 using namespace std; 3 vector<int> Amap[10010]; 4 int array[4]; 5 int start; 6 int end; 7 int sum=0; 8 int t=1; 9 int N,M; 10 void dfs(int n) 11 { 12 if(t==3){ 13 for(vector<int>::iterator iter=Amap[n].begin();iter<Amap[n].end();iter++){ 14 sum++; 15 } 16 sum--; 17 }else{ 18 for(vector<int>::iterator iter=Amap[n].begin();iter<Amap[n].end();iter++){ 19 array[t]=*iter; 20 if(t==1){ 21 t++; 22 dfs(*iter); 23 t--; 24 } 25 if(t==2){ 26 t++; 27 if(array[0]!=array[2]){ 28 dfs(*iter); 29 } 30 t--; 31 } 32 33 } 34 } 35 } 36 int main() 37 { 38 memset(Amap,0,sizeof(Amap)); 39 memset(array,0,sizeof(array)); 40 41 cin >> N>> M; 42 for(int i=0;i<M;i++){ 43 cin >> start >> end; 44 Amap[start].push_back(end); 45 Amap[end].push_back(start); 46 } 47 for(int i=1;i<=N;i++){ 48 array[0]=i; 49 dfs(i); 50 } 51 cout << sum; 52 return 0; 53 }
总结:当我们发现自己掌握的知识已经解决不了当前的问题时,我们一定要去学习,而学习到新的东西并且把问题解决的时候那种感觉真的令人很开心。就如这道题,其实我之前做题基本都是用数组,可能大部分的问题都可以用数组解决,但是如果测试数据要求数组分配的空间很大时,这是再用数组就不行了,由于之前在总结STL(https://www.cnblogs.com/henuliulei/p/10316994.html)的时候接触过vector但是在做题的时候并没有用过vector,而今天用vector把问题成功解决,真的让人感慨,多学点东西真的不吃亏,也许某天就用到了呢,,哈哈。
作者:你的雷哥
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。