题目描述
小W所在城市有n个学校(编号从1到n),学校与学校之间用一些双向道路连接。我们已知任意两个学校一定是可以相互导到达的(直接或间接)。
现在有两个学校a和b(1≤a,b≤n,a≠b)。假如当前有两个学校x和y(x≠a,x≠b,y≠a,y≠b),如果我们要从x走到y一定会经过a和b(经过a,b的顺序没有关系),那么我们就把这个x和y称为一个神奇的点对,注意x和y交换顺序也只能作为同一个点对。
现在,小W很好奇,他想要知道在这个城市里,这样的神奇点对有多少?
你的任务就是帮小W来统计这些神奇的点对。
输入
输入一行有4个正整数n,m,a,b,分别表示学校的数量,双向道路的数量还有两个特殊的学校a和b。
接下来有m行,每行两个整数vi和ui,表示ui和vi之间有一条双向道路,保证没有重复的边,也没有自环。
输出
输出一定要经过学校a和b的神奇的点对的数量。
样例
样例输入
【样例1】
7 7 3 5
1 2
2 3
3 4
4 5
5 6
6 7
7 5
【样例2】
4 5 2 3
1 2
2 3
3 4
4 1
4 2
【样例3】
4 3 2 1
1 2
2 3
4 1
样例输出
【样例1】
4
【样例2】
0
【样例3】
1
提示
样例1中,(1,6),(1,7),(2,6),(2,7)都是神奇的点对,因为它们相互到达一定会经过3和5。
样例2中,没有点对一定会经过2和3。
样例3中,只有点对(3,4)一定要经过1和2。
对于所有数据,1≤n≤100000,1≤a,b≤n,1≤m≤200000,a≠b,ui≠vi,所有的道路均不相同。
分析
若从x走到y一定会经过a和b(经过a,b的顺序没有关系),那么称x和y为一个神奇的点对(x和y交换顺序也只能作为同一个点对),求神奇点对的数量
对a,b分别跑一边dfs,分别求出 只能通过a前往b 和 只能通过b前往a 的点的数量,两者的乘积即为答案
代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100000 + 10,M = 200000 + 10;
int n,m,a,b;
int h[N],e[M * 2],ne[M * 2],idx;
bool st[N][2];
int cnt[2];
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs(int u,int op){
st[u][op] = true;
cnt[op]++;
for(int i = h[u];i != -1;i = ne[i]){
int j = e[i];
if(!st[j][op]) dfs(j,op);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
memset(h,-1,sizeof h);
cin >> n >> m >> a >> b;
for(int i = 1,u,v;i <= m;i++){
cin >> u >> v;
add(u,v),add(v,u);
}
st[a][0] = true;
dfs(b,0);
st[b][1] = true;
dfs(a,1);
int tmp = 0;
for(int i = 1;i <= n;i++)
if(st[i][0] && st[i][1]) tmp++;
cout << (cnt[0] - tmp + 1) * (cnt[1] - tmp + 1);
return 0;
}