D. 0-1ツリー(ステイン+カウント数)

タイトル

質問の意味:

    加重ツリー、0または1の重さを考えます。必要なポイントの数は(x、y)の私の条件を満たすように決定されます。XからYへの条件は、1重量後のパスに存在し、その後縁の右側を通ってゼロでなくてもよいです。
     2 n個 200000 1 バツ n個 0 C 1 2≤n≤200000,1≤x_i、y_i≤n、0≤c_i≤1

分析:

    分析後、ポイントは、0にすべて0または1再度、全体パス1のいずれかのため、条件を満たすことです。だから我々は、染色された通信ブロック0、右用通信ブロックの側面と1の右側だけを求めて行くことができます。染色した後、すべてゼロとすべてのものは容易に計算することができます。1次に0最初のために、我々は、ブロック0で通信する権利、および通信ブロック1のための右側の側で、2つの通信部01が、このことによってそれに接続することができ、両方の、ポイントの数を考えます答えが形成され、すなわち、図1に示すように、0が最初に後に計算されていることをこの時点でメモを除外する。

#include <iostream>
#include <vector> 
using namespace std;

typedef long long ll;

struct node{
	int num,val;
	node(int a,int b)
	{
		num = a;
		val = b;
	}
};

vector<node> g[200005];
int color1[200005],color2[200005],size1[200005],size2[200005];
int c1 = 1,c2 = 1;

void dfs1(int x,int fa)
{
	if( color1[fa] == 0 && fa != 0 )
	{
		color1[fa] = c1;
		size1[c1] ++;
	}
	for (int i = 0; i < g[x].size(); i++)
	{
		node t = g[x][i];
		if( color1[t.num] ) continue;
		if( t.val == 1 )
		{
			dfs1(t.num,x);
		}
	}
	if( color1[x] == 0 && fa != 0 )
	{
		color1[x] = c1;
		size1[c1] ++;
	}
}

void dfs2(int x,int fa)
{
	if( color2[fa] == 0 && fa != 0 )
	{
		color2[fa] = c2;
		size2[c2] ++;
	}
	for (int i = 0; i < g[x].size(); i++)
	{
		node t = g[x][i];
		if( color2[t.num] ) continue;
		if( t.val == 0 )
		{
			dfs2(t.num,x);
		}
	}
	if( color2[x] == 0 && fa != 0 )
	{
		color2[x] = c2;
		size2[c2] ++;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		int x,y,v;
		cin >> x >> y >> v;
		g[x].push_back(node(y,v));
		g[y].push_back(node(x,v)); 
	}
	for (int i = 1; i <= n; i++)
	{
		if( color1[i] == 0 ) 
		{
			dfs1(i,0);
			if( size1[c1] > 0 ) c1 ++;
		}
		if( color2[i] == 0 ) 
		{
			dfs2(i,0);
			if( size2[c2] > 0 ) c2 ++;
		}
	}
	ll ans = 0;
	//cout << c1 << ' ' << size1[c1-1] << ' ' << c2 << ' ' << size2[c2-1] << '\n';
	for (int i = 1; i < c1; i++)
	{
		ans += (ll)( size1[i] - 1 ) * size1[i];
	}
	for (int i = 1; i < c2; i++)
	{
		ans += (ll)( size2[i] - 1 ) * size2[i];
	}
	for (int i = 1; i <= n; i++)
	{
		if( color1[i] != 0 && color2[i] != 0 )
		{
			ans += (ll)(size2[color2[i]] - 1) * ( size1[color1[i]] - 1 ); 
		}
	}
	cout << ans << '\n';
	return 0;
}

公開された132元の記事 ウォンの賞賛6 ビュー7926

おすすめ

転載: blog.csdn.net/weixin_44316314/article/details/104874480