Southeastern European Regional Programming C Bucharest, Romania – Vinnytsya, Ukraine C Tree
链接:https://codeforces.com/group/xrTA2IaQje/contest/254611/problem/C
题意:树中选择m个黑点(已知的若干),使之直径最短;
题解:在看了学校巨佬mz的博客下明白了这题是一个Floyd的枚举题,其实说是性质(一个重要性质,也就是当一棵树存在一个直径时,加入点能够满足这个直径还是直径只需要满足这个新加入的点到两个端点的距离不超过直径距离,所以直接暴力枚举两个端点,然后看能不能加入m个点,如果可以就更新答案)但是自己肯定能想到,其他点根本没有直径长啊,加入就完事了呗。
感谢巨佬!
锵锵~代码环节,YES!!!
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 110;
int n,m;
int mp[maxn][maxn];
bool p[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d",&p[i]);
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j)mp[i][j]=0;
else mp[i][j]=inf;
}
}
for(int i=1; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=1;
mp[y][x]=1;
}
for(int k=1; k<=n; k++)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(mp[i][j]>mp[i][k]+mp[k][j])
{
mp[i][j]=mp[i][k]+mp[k][j];
}
}
}
}
int ans=inf;
int num=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(p[i]&&p[j])
{
num=0;
for(int k=1; k<=n; k++)
{
if(!p[k])continue;
if(mp[i][j]>=mp[i][k]&&mp[i][j]>=mp[k][j])
{
num++;
}
if(num==m)break;
}
if(num==m)ans=min(ans,mp[i][j]);
}
}
}
cout<<ans<<endl;
return 0;
}