一名苦逼的OIer,想成为ACMer

Iowa_Battleship

BZOJ4813或洛谷3698 [CQOI2017]小Q的棋盘

BZOJ原题链接

洛谷原题链接

贪心或树形\(DP\)都可做,但显然\(DP\)式子不好推(因为我太菜了),所以我选择贪心。
很显然从根出发主干走最长链是最优的,而剩下的点每个都需要走两步,所以用除去走最长链的步数的剩余步数除\(2\)(下取整)就是剩余能走的点数。

#include<cstdio>
using namespace std;
const int N = 110;
const int M = N << 1;
int fi[N], di[M], ne[M], de[N], l, ma_de, ma_id;
inline int re()
{
	int x = 0;
	char c = getchar();
	bool p = 0;
	for (; c < '0' || c > '9'; c = getchar())
		p |= c == '-';
	for (; c >= '0' && c <= '9'; c = getchar())
		x = x * 10 + c - '0';
	return p ? -x : x;
}
inline void add(int x, int y)
{
	di[++l] = y;
	ne[l] = fi[x];
	fi[x] = l;
}
inline int minn(int x, int y)
{
	return x < y ? x : y;
}
void dfs(int x)
{
	int i, y;
	if (ma_de < de[x])
	{
		ma_de = de[x];
		ma_id = x;
	}
	for (i = fi[x]; i; i = ne[i])
		if (!de[y = di[i]])
		{
			de[y] = de[x] + 1;
			dfs(y);
		}
}
int main()
{
	int i, n, m, x, y;
	n = re();
	m = re();
	for (i = 1; i < n; i++)
	{
		x = re() + 1;
		y = re() + 1;
		add(x, y);
		add(y, x);
	}
	de[1] = 1;
	dfs(1);
	if (m <= ma_de - 1)
	{
		printf("%d", m + 1);
		return 0;
	}
	m -= ma_de - 1;
	printf("%d", ma_de + minn(m >> 1, n - ma_de));
	return 0;
}

posted on 2018-11-01 14:57  Iowa_Battleship  阅读(114)  评论(0编辑  收藏  举报

导航