描述
為了拯救喵哈哈村,這個世界必須要存在英雄。
一名叫做盧西奧的英雄站了出來!他現在面臨乙個難題:
他被要求將一棵樹拆成3份,使得每乙份中所有節點的權值和相等。
他希望知道,對於一棵給定的有根樹,在選取其中2個非根節點並將它們與它們的父親節點分開後,所形成的三棵子樹的節點權值之和能夠兩兩相等的方案有多少種。
兩種方案被看做不同的方案,當且僅當形成方案的2個節點不完全相同。
輸入
每個輸入檔案包含多組輸入,在輸入的第一行為乙個整數t,表示資料的組數。
每組輸入的第一行為乙個整數n,表示給出的這棵樹的節點數。
接下來n行,依次描述結點1~n,其中第i行為兩個整數vi和pi,分別描述這個節點的權值和其父親節點的編號。
父親節點編號為0的節點為這棵樹的根節點。
滿足3<=n<=100000, |vi|<=100, t<=10
輸出
對於每組輸入,輸出一行ans,表示方案的數量。
樣例輸入1
231 0
1 11 2
41 0
1 11 2
1 3
樣例輸出1
1兩種情況:0題解
第一種情況,有兩個是子樹,這個東西用啟發式合併/dp去維護一下當前sz[x]=all/3的個數就好了。
第二種情況,只有乙個是子樹,那麼第二段顯然是包含了第一段的,那麼就存在乙個的size=2all/3,乙個sz=all/3的情況,統計一下就好了。
dfs處理一下就好了,具體看**:
#include// #include using namespace std;
#define ff first
#define ss second
#define mp make_pair
#define pb push_back
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define for(i, n, m) for(int i = n; i <= m; i++)
#define rep(i, n, m) for(int i = n; i >= m; i--)
#define ll long long
typedef long long ll;
typedef pair pii;
typedef pairpll;
typedef unsigned long long ull;
/****************************define***************************************/
const int mod = 1e9 + 7;
const int maxn = 100010;
int n;
int v[maxn], sz[maxn], p[maxn];
vector nd[maxn];
int s;
int cn = 0, cn2 = 0;
ll ans = 0;
void dfs_sz(int u)
}void dfs(int u)
if(p[u] != 0 && sz[u] == s*2/3) cn2++;
int t = nd[u].size();
for(i, 0, t-1)
if(sz[u] == s/3) cn++;
if(p[u] != 0 && sz[u] == s*2/3) cn2--;
}int main()
if(s % 3 != 0) cout << 0 << endl;
else
}return 0;
}
qscoj 喵哈哈村的盧西奧
描述為了拯救喵哈哈村,這個世界必須要存在英雄。一名叫做盧西奧的英雄站了出來!他現在面臨乙個難題 他被要求將一棵樹拆成3份,使得每乙份中所有節點的權值和相等。他希望知道,對於一棵給定的有根樹,在選取其中2個非根節點並將它們與它們的父親節點分開後,所形成的三棵子樹的節點權值之和能夠兩兩相等的方案有多少種...
qscoj 喵哈哈村的盧西奧 樹形DP難)
描述為了拯救喵哈哈村,這個世界必須要存在英雄。一名叫做盧西奧的英雄站了出來!他現在面臨乙個難題 他被要求將一棵樹拆成3份,使得每乙份中所有節點的權值和相等。他希望知道,對於一棵給定的有根樹,在選取其中2個非根節點並將它們與它們的父親節點分開後,所形成的三棵子樹的節點權值之和能夠兩兩相等的方案有多少種...
喵哈哈村的排隊
描述有一堆喵哈哈村的村民們在排隊,他們從佇列的尾部開始標號,標號為1的村民站在最後面,標號為n的村民站在佇列的最前面,而且每個村民都擁有乙個智商值a i 這些村民有時候會覺得不開心,因為他們覺得憑什麼乙個智商比他低的人,可以站在他的前面!現在對於每個村民,他們都想知道,在他前面,智商比他低,離他最遠...