X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如下图所示的网络。
1 -> 2 -> 3 -> 1 是允许的
1 -> 2 -> 1 -> 2 或者 1 -> 2 -> 3 -> 2 都是非法的。
Input
输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
Output
输出一个整数,表示满足要求的路径条数。
Sample Input
样例输入1 3 3 1 2 2 3 1 3 样例输入2 4 4 1 2 2 3 3 1 1 4
Sample Output
样例输出1 6 样例输出2 10
Source
蓝桥杯
合法路径:
1.最多走过4个结点
2.终点可以和起点相同或者不同
3.走过的点不能当终点,也就是说终点不能和路径中间的两个点一样
1.最多走过4个结点
2.终点可以和起点相同或者不同
3.走过的点不能当终点,也就是说终点不能和路径中间的两个点一样
深搜合法路径计数就好
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define INF 99999999 #define me(a,x) memset(a,x,sizeof(a)) int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}}; int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};//i的阶乘 LL getval() { LL ret(0); char c; while((c=getchar())==' '||c==' '||c==' '); ret=c-'0'; while((c=getchar())!=' '&&c!=' '&&c!=' ') ret=ret*10+c-'0'; return ret; } void out(int a) { if(a>9) out(a/10); putchar(a%10+'0'); } int kt(int a[],int n)//康托展开 { int ans=0; for(int i=1; i<=n; i++) //下标从1开始 { int c=0; for(int j=i+1; j<=n; j++) { if(a[j]<a[i]) c++; } ans+=(c*fac[n-i]); } return ans+1; } #define max_v 10005 vector<int> G[max_v]; int vis[max_v]; int ans; void dfs(int s,int cur,int step)//起点是s,当前点是cur,当前步数是step { if(step<=2)//步数小于2,继续深搜 { for(int i=0;i<G[cur].size();i++) { int next=G[cur][i];//下一步要走的点 if(vis[next]==0)//没有走过 { vis[next]=1; dfs(s,next,step+1); vis[next]=0;//回退 } } } if(step==3)//步数等于3,只要可以找到合格的终点就好了,不用继续深搜 { for(int i=0;i<G[cur].size();i++) { int f=G[cur][i];//终点 if(vis[f]==0)//终点没有访问过 ans++; if(f==s)//终点和源点重合 ans++; } } } int main() { int n,m; scanf("%d %d",&n,&m); int x,y; for(int i=1;i<=m;i++) { scanf("%d %d",&x,&y); G[x].push_back(y); G[y].push_back(x); } me(vis,0); ans=0; for(int i=1;i<=n;i++) { vis[i]=1; dfs(i,i,1);//以起点是i,当前点是i,步数是1开始深搜 vis[i]=0;//回退 状态回退是深搜的重要标志之一!!! } printf("%d ",ans); } /* 合法路径: 1.最多走过4个结点 2.终点可以和起点相同或者不同 3.走过的点不能当终点,也就是说终点不能和路径中间的两个点一样 深搜合法路径计数就好 */