題意:
給定一個n個點,n-1條邊的無向圖,途中任意兩點聯通,並給出節點x,y,計算圖上兩點(u,v)之間的最短路徑依次經過x,y的對數,(u,v)與(v,u)視作不同一對,求總對數-符合條件的對數
-------------------------------------------------------------------------------------------------------
Solution:
顯然這個圖是一棵樹, 由於是無向圖,可以將圖中任意一個節點作爲樹根建樹
那麼可以將y作爲樹根,x則是樹y的某一個節點,
設s[i]爲子樹i的size(包括i本身),節點z爲(y,x)路徑上y的兒子節點
符合條件的對數爲(y,x)路徑兩端的節點數相乘,即s[x]*(s[y]-s[z]),用n(n-1)減去就可以得出答案
------------------------------------------------------------------------------------------------------
鄰接表存圖,s[]用遞歸的dfs完成,尋找而節點z同樣用dfs的遞歸標記
------------------------------------------------------------------------------------------------------
Code:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#include <queue>
#define ll long long
using namespace std;
const int MAXN=3e5+10;
int n,x,y,z;
int head[MAXN],nume;
int size[MAXN];
bool tag[MAXN],vis[MAXN];
struct Edge
{
int nex,to;
}e[MAXN*2];
inline int in()
{
int x=0,flag=1;
char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') flag=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
void addedge(int from,int to)
{
e[++nume]=(Edge){head[from],to};
head[from]=nume;
}
int dfs(int u)
{
vis[u]=true;
size[u]++;
if (u==x) tag[u]=true;
for (int i=head[u];i;i=e[i].nex)
{
int v=e[i].to;
if (!vis[v])
{
dfs(v);
size[u]+=size[v];
if (tag[v])
{
tag[u]=1;
if (u==y) z=v;
}
}
}
}
int main()
{
n=in();
x=in();y=in();
for (int i=1;i<n;i++)
{
int u=in(),v=in();
addedge(u,v);
addedge(v,u);
}
dfs(y);
cout<<(ll)n*(n-1)-(ll)size[x]*(size[y]-size[z]);
return 0;
}