noip2018信心赛day2画画(二分图)

画画

lyh初赛结束后,选择学习画画。一天,lyh在纸上画了一棵 个节点的树。
而lyh认为世界上可以被分成两半的东西是优美的。所以对于一个图来说,如果它是二分图,那么它就是优美的。 lyh想知道,最多能给这个图插入多少条边,使得这个图仍是优美的,显然树一定是优美的。 由于lyh要去见自己的另一半,于是这个问题就交给你了。

Input
输入文件为
第一行一个整数 ,表示树的节点数。
接下来 行,每行两个整数 和 ,表示一条从 连向 的边。
Output
输入文件为
一行一个整数,表示答案。
Sample Input1
3 1 2
1 3
Sample Output1
0
Sample Input2
5
1 2 2 3
3 4 4 5
Sample Output2
2
Data Constraint
对于40%数据,满足 n<=10
对于100%数据,满足n<=100000

分析:奇点个数*偶点个数-n+1

代码

#include 
#define N 300005
#define ll long long
using namespace std;

struct arr
{
	int to,nxt;
}a[N];
int num[N],siz[N],n,deep;
int l,ls[N];
ll sum1[N],sum2[N],sum[N];

void add(int x, int y)
{
	a[++l].to = y;
	a[l].nxt = ls[x];
	ls[x] = l;
}

int read()
{
	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;
}

void dfs(int x, int fa, int dep)
{
	num[dep]++;
	if (dep > deep) deep = dep;
	for (int i = ls[x]; i; i = a[i].nxt)
		if (a[i].to != fa) 
		{
			dfs(a[i].to, x, dep + 1);
			siz[x]++;
		}
}

int main()
{
	freopen("draw.in","r",stdin);
	freopen("draw.out","w",stdout);
	scanf("%d", &n);
	for (int i = 1; i < n; i++)
	{
		int x, y;
		x = read(), y = read();
		add(x, y);
		add(y, x);
	}
	dfs(1, 0, 1);
	sum[1] = num[1];
	sum[2] = num[2];
	for (int i = 3; i <= n; i++)
		sum[i] = sum[i - 2] + num[i];
	int d1, d2;
	if (deep % 2 == 1) d1 = deep, d2 = deep - 1;
		else d2 = deep, d1 = deep - 1;
	ll ans = 0;
	for (int i = 1; i <= deep; i++)
	{
		int x = i + 3;
		if (i > 1) ans += (num[i - 1] - 1) * num[i];
		if (x % 2 == 1)
		{
			if (x > d1) continue;
			ans += (sum[d1] - sum[i + 1]) * num[i];
		}
		else
		{
			if (x > d2) continue;
			ans += (sum[d2] - sum[i + 1]) * num[i];
		}
	}
	printf("%lld", ans);
	fclose(stdin);
	fclose(stdout);
}

你可能感兴趣的:(noip2018信心赛day2画画(二分图))