题意简述:给出无向图,会有重边,然后给你两个点a,b,让你计算有多少点对(x,y)满足从x到y的所有路径都经过a和b
题解:先从a,b两点出发进行dfs,dfs的过程中不能经过a,b两点(除了开始)
所有的点分为了三类,第一类是a能到但是b到不了,第二类是b能到但是a到不了,第三类是a,b都能到
首先每一类点的内部之间的点对对答案没有贡献,因为他们之间到达可以只经过a,b其中一个点
所以只需要考虑不同类之间的点对答案的贡献
第一类和第三类对答案没有贡献,因为对于点对x,y,x可以先a再到y,而不需要今过b点,因此没有贡献
同理第二类对第三类也没有贡献
第一类和第二类,他们相通必须经过a,b两点
因此答案就是第一类的点数×第二类的点数
const int maxn=2e5+5; const int maxm=1e6+5; const int inf=1e9; int n,m,a,b; int head[maxn],ver[maxm],nex[maxm],tot; void inline AddEdge(int x,int y){ ver[++tot]=y,nex[tot]=head[x],head[x]=tot; } bool vis[maxn]; int cnt[maxn]; void dfs(int x,int f){ vis[x]=1; cnt[x]+=f; for(int i=head[x];i;i=nex[i]){ int y=ver[i]; if(!vis[y] && y!=a && y!=b) { dfs(y,f); } } } void solve(){ cin>>n>>m>>a>>b; tot=0; for(int i=1;i<=n;i++) head[i]=0; for(int i=0;i<m;i++){ int x,y; scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } for(int i=1;i<=n;i++) vis[i]=cnt[i]=0; dfs(a,1); for(int i=1;i<=n;i++) vis[i]=0; dfs(b,2); ll s1=0,s2=0; for(int i=1;i<=n;i++){ // cout<<cnt[i]<<endl; if(i!=a && i!=b) { if(cnt[i]==1) s1++; else if(cnt[i]==2) s2++; } } //cout<<s1<<' '<<s2<<endl; printf("%lld ",s1*s2); } int main(){ int t; cin>>t; while(t--) solve(); }