P2538 [SCOI2008]城堡 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

贪心。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 55
int n, m, k, r[N], d[N], p[N], temp[N], dis[N][N], vis[N];
void search(int x)
{
	memset(temp, 0, sizeof(temp));
	for(int i = 1; i <= n; i++)
	{
		if(!vis[i])
		{
			for(int j = 1; j <= n; j++)
			{
				if(dis[i][j] <= x)
				{
					temp[j]++;
				}
			}
		}
	}
	int num = 1;
	for(int i = 2; i <= n; i++)
	{
		if(temp[i] >= temp[num])
		{
			num = i;
		}
	}
	for(int i = 1; i <= n; i++)
	{
		if(dis[num][i] <= x)
		{
			vis[i] = 1;
		}
	}
	return;
}
int check(int x)
{
	memset(vis, 0, sizeof(vis));
	for(int i = 1; i <= m; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			if(dis[p[i]][j] <= x)
			{
				vis[j] = 1;
			}
		}
	}
	for(int i = 1; i <= k; i++)
	{
		search(x);
	}
	for(int i = 1; i <= n; i++)
	{
		if(!vis[i])
		{
			return 0;
		}
	}
	return 1;
}
signed main()
{
	int L = 0, R = 0, mid;
	scanf("%d%d%d", &n, &m, &k);
	for(int i = 1; i <= n; i++)
	{
		scanf("%d", &r[i]);
		r[i]++;
	}
	for(int i = 1; i <= n; i++)
	{
		scanf("%d", &d[i]);
	}
	for(int i = 1; i <= m; i++)
	{
		scanf("%d", &p[i]);
		p[i]++;
	}
	memset(dis, 0x3f, sizeof(dis));
	for(int i = 1; i <= n; i++)
	{
		dis[i][i] = 0;
		R += d[i];
		dis[i][r[i]] = dis[r[i]][i] = min(dis[i][r[i]], d[i]);
	}
	for(int k = 1; k <= n; k++)
	{
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
			{
				if(i == j || j == k || i == k)
				{
					continue;
				}
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
			}
		}
	}
	while(L < R)
	{
		mid = (L + R) >> 1;
		if(check(mid))
		{
			R = mid;
		}
		else
		{
			L = mid + 1;
		}
	}
	printf("%d", L);
	return 0;
}