链接:F1 - Tree Cutting (Easy Version)
题意:
给一棵有n个结点的树,每个结点有有三种情况,蓝色,黑色,红色
给定n-1条边
问:如果删掉一条边,使得到的两个子树中,一棵子树包含所以蓝点,另一颗包含红点,有多少种删边方法
解析:
遍历这棵树,分别累计子节点的蓝点和红点数目
如果如果子节点包含所以蓝色点,且没有红色点
或者子节点包含所以红色点,且没有蓝色点
就可以删除这条边
ac:
#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
vector<int> vc[MAXN];
int a[MAXN],red[MAXN],blue[MAXN];
int ans=0;
void dfs(int x,int pre)
{
if(a[x]==1)
red[x]++;
else if(a[x]==2)
blue[x]++;
int len=vc[x].size();
for(int i=0;i<len;i++)
{
int v=vc[x][i];
if(v==pre)
continue;
dfs(v,x);
red[x]=red[x]+red[v];
blue[x]=blue[x]+blue[v];
if((red[v]==red[0]&&blue[v]==0)||(blue[v]==blue[0]&&red[v]==0))//子树只有一种颜色且没有另外的颜色
ans++;
}
}
int main()
{
int n,u,v;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==1)//红点
red[0]++;
else if(a[i]==2)//蓝点
blue[0]++;
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
vc[u].push_back(v);
vc[v].push_back(u);
}
ans=0;
dfs(1,0);
printf("%d\n",ans);
return 0;
}