Codeforces 979C

題意:

給定一個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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章