Problem:
给定一棵n个点的树,问其中有多少条长度为偶数的路径。路径的长度为经过的边的条数。x到y与y到x被视为同一条路径。
路径的起点与终点不能相同。
Solution:
解法一:
路径为偶数,也就是经过偶数跳边,由于是一棵树,所以统计从根出发经过偶数条边的点的个数和奇数条边的个数(也就是深度为奇数和偶数)
最后就是一个排列组合的问题了(奇数的选一条 + 奇数的再选一条)的种数 +(偶数选一条 + 偶数再选一条)的种数
解法二:
对于每一颗子树,统计以子树为根,每个点到根的距离奇数的有几个,偶数的有几个,然后在回溯时统计答案
答案 += 当前节点的奇数边条数 * 父节点偶数边条数 + 当前节点偶数边条数 * 父节点奇数边条数
(由于当前节点到父节点还有一条边,所以对于当前节点来说,其实它加上这条边后奇偶就互换了,所以可以理解为当前为根节点的子树中新加入的偶数边条数 * 之前存在的偶数边条数 + 当前为根节点的子树中新加入的奇数边条数 * 之前存在的奇数边条数)
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define _for(i,s,t) for(int i=s;i<t;i++)
#define _rof(i,s,t) for(int i=s;i>t;i--)
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define Ri(x) scanf("%d",&x)
#define Rii(x,y) scanf("%d%d",&x,&y)
#define INF 0x3f3f3f3f
using namespace std;
template<class T>inline void read(T &res)
{
char c;T flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
typedef long long ll;
const int maxn = 1e5 + 10;
int n,odd,even;
ll ans;
vector<int> G[maxn << 1];
// ---------------------- 解法一 ----------------------------
void dfs(int nowp,int fa,int dep){
(dep & 1)?(++even):(++odd);
_for(i,0,G[nowp].size()){
if(G[nowp][i] != fa){
dfs(G[nowp][i],nowp,!dep);
}
}
}
void solve1(){
dfs(1,0,0);
cout<<((odd*1ll * (odd - 1)*1ll)>>1) + ((even*1ll * (even - 1)*1ll)>>1)<<endl;
}
// ------------------------------- 解法二 ----------------------------------
int dp[maxn][2];// 节点i的子树中奇偶边条数 0:偶,1:奇
void dfs2(int nowp,int fa){
dp[nowp][0] = 1;
_for(i,0,G[nowp].size()){
if(G[nowp][i] != fa){
int to = G[nowp][i];
dfs2(to,nowp);
ans += dp[nowp][1] * dp[to][0] + dp[nowp][0] * dp[to][1];
dp[nowp][0] += dp[to][1];
dp[nowp][1] += dp[to][0];
}
}
}
void solve2(){
dfs2(1,0);
cout<<ans<<endl;
}
int main(){
IOS;
int x,y;
cin>>n;
rep(i,2,n){
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
//solve1();
solve2();
return 0;
}
/**
Problem:
给定一棵n个点的树,问其中有多少条长度为偶数的路径。路径的长度为经过的边的条数。x到y与y到x被视为同一条路径。
路径的起点与终点不能相同。
Solution:
解法一:
路径为偶数,也就是经过偶数跳边,由于是一棵树,所以统计从根出发经过偶数条边的点的个数和奇数条边的个数(也就是深度为奇数和偶数)
最后就是一个排列组合的问题了(奇数的选一条 + 奇数的再选一条)的种数 +(偶数选一条 + 偶数再选一条)的种数
解法二:
对于每一颗子树,统计以子树为根,每个点到根的距离奇数的有几个,偶数的有几个,然后在回溯时统计答案
答案 += 当前节点的奇数边条数 * 父节点偶数边条数 + 当前节点偶数边条数 * 父节点奇数边条数
(由于当前节点到父节点还有一条边,所以对于当前节点来说,其实它加上这条边后奇偶就互换了,所以可以理解为当前为根节点的子树中新加入的偶数边条数 * 之前存在的偶数边条数 + 当前为根节点的子树中新加入的奇数边条数 * 之前存在的奇数边条数)
*/ 


京公网安备 11010502036488号