# 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞

## 3697: 采药人的路径

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 681  Solved: 246
[Submit][Status][Discuss]

7
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1

1

## 3127: [Usaco2013 Open]Yin and Yang

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 116  Solved: 82
[Submit][Status][Discuss]

## Description

Farns (1 <= N <= 100,000) which are connected by N-1 edges such that he can reach any barn from any other. Farmer John wants to choose a path which starts and ends at two different barns, such that he does not traverse any edge twice. He worries that his path might be a little long, so he also wants to choose another "rest stop" barn located on this path (which is distinct from the start or the end). Along each edge is a herd of cows, either of the Charcolais (white hair) or the Angus (black hair) variety. Being the wise man that he is, Farmer John wants to balance the forces of yin and yang that weigh upon his walk. To do so, he wishes to choose a path such that he will pass by an equal number of Charcolais herds and Angus herds-- oth on the way from the start to his rest stop, and on theway from the rest stop to the end. Farmer John is curious how many different paths he can choose that  are "balanced" as described above. Two paths are different only if they consist of different setsof edges; a path should be counted only once even if there are multiple valid "rest stop" locationsalong the path that make it balanced. Please help determine the number of paths Farmer John can cho

## Input

* Line 1: The integer N.
* Lines 2..N: Three integers a_i, b_i and t_i, representing the two barns that edge i connects. t_i
is 0 if the herd along that edge is Charcolais, and 1 if the herd is Angus.

## Output

Line 1: One integer, representing the number of possible paths Farmer John can choose from.

## Sample Input

7
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1
INPUT DETAILS:
There are 7 barns and 6 edges. The edges from 1 to 2, 2 to 4 and 2 to 5 have Charcolais herds along
them.

## Sample Output

1
OUTPUT DETAILS:
No path of length 2 can have a suitable rest stop on it, so we can only consider paths of length 4.
The only path that has a suitable rest stop is 3-1-2-5-7, with a rest stop at 2.

Gold

## Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 100010
#define LL long long
int N;
struct EdgeNode{int next,to,val;}edge[MAXN<<1];
void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].val=w;}
void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
int size[MAXN],maxx[MAXN],root,Sz; bool visit[MAXN];
void DFSRoot(int now,int last)
{
size[now]=1; maxx[now]=0;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to])
{
DFSRoot(edge[i].to,now);
size[now]+=size[edge[i].to];
maxx[now]=max(maxx[now],size[edge[i].to]);
}
maxx[now]=max(maxx[now],Sz-size[now]);
if (maxx[now]<maxx[root]) root=now;
}
int deep[MAXN],maxd,md,mark[MAXN<<1],D[MAXN<<1];
LL f[MAXN<<1][2],g[MAXN<<1][2],ans;
void DFS(int now,int last)
{
maxd=max(maxd,deep[now]);
if (mark[D[now]]) f[D[now]][1]++; else f[D[now]][0]++;
mark[D[now]]++;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last && !visit[edge[i].to])
{
deep[edge[i].to]=deep[now]+1;
D[edge[i].to]=D[now]+edge[i].val;
DFS(edge[i].to,now);
}
mark[D[now]]--;
}
void Get(int x,int val)
{
D[x]=N+val; deep[x]=1;
maxd=1; DFS(x,0); md=max(maxd,md);
ans+=(g[N][0]-1)*f[N][0];
for (int i=-maxd; i<=maxd; i++)
ans+=g[N-i][1]*f[N+i][1]+g[N-i][0]*f[N+i][1]+g[N-i][1]*f[N+i][0];
for (int i=N-maxd; i<=N+maxd; i++)
g[i][0]+=f[i][0],g[i][1]+=f[i][1],f[i][0]=f[i][1]=0;
}
void Divide(int x)
{
visit[x]=1;
g[N][0]=1; md=0;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to]) Get(edge[i].to,edge[i].val);
for (int i=-md; i<=md; i++) g[N+i][0]=g[N+i][1]=0;
for (int i=head[x]; i; i=edge[i].next)
if (!visit[edge[i].to])
{
Sz=size[edge[i].to]; root=0;
DFSRoot(edge[i].to,x);
Divide(root);
}
}
int main()
{
}