历届试题 网络寻路

问题描述

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加剪枝。依次从每个节点出发,找到一个长度为四的路径,可以为环,保证第一个节点不可以和第二个第三个节点相同,第四个节点不可以和第三个节点的和第二个节点相同
代码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把问题成功解决,真的让人感慨,多学点东西真的不吃亏,也许某天就用到了呢,,哈哈。

转载于:https://www.cnblogs.com/henuliulei/p/10492914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值