1. 程式人生 > >藍橋杯 歷屆試題 網路尋路(dfs搜尋合法路徑計數)

藍橋杯 歷屆試題 網路尋路(dfs搜尋合法路徑計數)

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)。

輸入資料保證任意兩點最多隻有一條邊連線,並且沒有自己連自己的邊,即不存在重邊和自環。

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.走過的點不能當終點,也就是說終點不能和路徑中間的兩個點一樣 深搜合法路徑計數就好  
#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=='\n'||c=='\r'); ret=c-'0'; while((c=getchar())!=' '&&c!='\n'&&c!='\r') 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\n",ans); } /* 合法路徑: 1.最多走過4個結點 2.終點可以和起點相同或者不同 3.走過的點不能當終點,也就是說終點不能和路徑中間的兩個點一樣 深搜合法路徑計數就好 */