路径统计(dfs)

题目描述
小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,所有的道路均不相同。

思路
对a,b跑dfs,分别求只能通过a前往b和通过b前往a的点的数量,答案为两者乘积

代码实现

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=200005;
const int M=35;
const int INF=0x3f3f3f;
const ull sed=31;
const ll mod=1e9+7;
const double eps=1e-8;
typedef pair<int,int>P;
typedef pair<double,double>Pd;
 
int n,m,a,b;
vector<int>E[N];
bool vis[2][N];
ll cnt[2];
 
void add(int u,int v)
{
    E[u].push_back(v);
    E[v].push_back(u);
}
 
void dfs(int u,int p)
{
    if(vis[p][u]) return ;
    cnt[p]++;
    vis[p][u]=true;
    for(int i=0;i<E[u].size();i++)
    {
        int v=E[u][i];
        if(vis[p][v]) continue;
        dfs(v,p);
    }
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&a,&b);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    vis[0][b]=true;
    dfs(a,0);
    vis[1][a]=true;
    dfs(b,1);
    ll scnt=0; 
    for(int i=1;i<=n;i++) if(vis[0][i] && vis[1][i]) scnt++;
    printf("%lld\n",(cnt[0]-scnt+1)*(cnt[1]-scnt+1));
    return 0;
}
 
发布了235 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43935894/article/details/104137934