NC14248

NC14248

題意

給定一棵n個點的樹,問其中有多少條長度爲偶數的路徑。路徑的長度爲經過的邊的條數。x到y與y到x被視爲同一條路徑。路徑的起點與終點不能相同

思路

DFS 樹 數據結構
這道題和CF1339D十分相像,有興趣的可以做一下。

把題意轉化爲給你一顆n個結點的樹,樹上所有的邊權值爲1,求樹上任意兩點距離爲偶數的點的個數。
問題就轉化爲了如何獲取樹上任意兩點的距離是否爲偶數呢?
圖論相關的問題離不開畫圖,所以我們簡單畫個圖。
受CF1339D給我的啓發,無根樹可以找一個根先固定,而根如果找任意點會帶來討論的麻煩,所以找一個葉子節點最合適不過。
令任意一片葉子爲根節點,並及以葉子結點爲1號點,加上其深度擴展其他點,其之間的距離差就爲其標記的差的絕對值。
在這裏插入圖片描述
重要性質:距離爲偶數的點節點標記的奇偶性相同
好了我們現在找任意一片葉子結點進行dfs,分別記錄節點爲偶數的個數和奇數的個數。(初始化爲-1,表示一個奇數或偶數的點出現是不會存在偶數邊的,必須要有一對)
任意兩個點就是(n+1)n2(n+1)*\frac{n}{2}

擴展小技巧:

CF裏偷學Div1的大佬們的寫法,如果只判斷奇偶性的話我們其實還可以令其節點爲1或者0,然後進行異或即可。
如上圖如果按照異或來就是:
在這裏插入圖片描述
只需要將代碼中的dfs(c,u,d+1)改爲dfs(c,u,d^1)即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 1e5 + 5;

vector<int>G[N];
ll n,cnt=-1,tot=-1;

void dfs(int u,int fa,int d){
	if(d&1) cnt++;
	else tot++;
	for(auto c:G[u]){
		if(c==fa) continue;
		dfs(c,u,d+1);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int x,y;cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(G[i].size()==1) {dfs(i,-1,1);break;}
	}
	cout<<(cnt+1)*cnt/2+(tot+1)*tot/2<<'\n';
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章