X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如图 11 所示的网络。
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)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
输出格式
输出一个整数,表示满足要求的路径条数。
输入输出样例
输入
3 3 1 2 2 3 1 3
输出
6
输入
4 4 1 2 2 3 3 1 1 4
输出
10
说明/提示
时限 1 秒, 64M。蓝桥杯 2013 年第四届国赛
解法一(暴搜)
#include<iostream>
#include<vector>
using namespace std;
int n,m,ans,f;
vector<int>e[100005];
bool vis[10005];void dfs(int a,int b){if(b==4)ans++; //到达第四个节点,方案数加一 else{for(int i=0;i<e[a].size();i++){ //遍历a节点的所有子节点 int v=e[a][i];if(!vis[v]){ //如果该点还未使用 vis[v]=1;dfs(v,b+1); vis[v]=0; //回溯 }else if(b==3&&v==f)dfs(v,b+1); //如果已经走了两步了,下一个为置又回到原点也是一种可行方案 }}
}int main(){cin>>n>>m;int x,y,k=m;while(k--){ //因为是双向传输,所以要存两个节点 cin>>x>>y;e[x].push_back(y);e[y].push_back(x);}for(int i=1;i<=n;i++){ //从第一个节点开始遍历,依次枚举所有节点 vis[i]=1;f=i;dfs(f,1); vis[i]=0;}cout<<ans<<endl;return 0;
}
解法二(中转边)借鉴dalao的
一条边的两个节点如果还连有其它边,就两边相乘,因为是双向的就再乘以2
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;struct Node{int u,v;
}h[N];
int n,m;
LL a[10005];int main(){cin>>n>>m;memset(a,0,sizeof a);for(int i=1;i<=m;i++){cin>>h[i].u>>h[i].v;a[h[i].u]++;a[h[i].v]++; }LL ans=0;for(int i=1;i<=m;i++){int u=h[i].u;int v=h[i].v;ans+=(a[u]-1)*(a[v]-1)*2;}cout<<ans<<endl;return 0;
}