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;
}