无向图经过K个顶点的最少花费,每条路的权值相等均为1
# include <stdio.h>
# include <string.h>
# include <algorithm>
# include <vector>
using namespace std;
const int MAXN=1e4+10;
const int INF=1e7;
vector<int>vec[MAXN];
int vis[MAXN];
int ans[MAXN],num,longest,ending;
void dfs (int u,int fa,int deep)
{
num++;
vis[u]=1;
if(deep>longest)
{
longest=deep;
ending=u; //记录最长链的结束顶点
}
for(int i=0;i<vec[u].size();i++)
{
int v=vec[u][i];
if(v!=fa)
{
dfs(v,u,deep+1);
}
}
}
void solve (int k) //num记录从k出发可以到达的点的个数,longest记录路径中最长的链的长度
{
num=0;
longest=0;
dfs(k,-1,1);
longest=0;
num=0;
dfs(ending,-1,1); //两遍dfs保证所找的链是当前连通图中最长的,第二遍主要是更新longest,num实际上是不变的
for(int i=1;i<=longest;i++)
{
ans[i]=min(ans[i],i-1);
}
for(int i=longest+1;i<=num;i++)
{
ans[i]=min(ans[i],2*i-longest-1);
}
}
int main ()
{
int t,n,m,u,v,k,q;
scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) vec[i].clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=MAXN;i++)
{
ans[i]=INF;
}
for(int i=1;i<=n;i++)
{
if(!vis[i]) solve(i); //相当于在每一个连通分量中更新最少花费的值
}
scanf("%d",&k);
printf("Case %d:\n",ca);
while(k--)
{
scanf("%d",&q);
if(ans[q]==INF) printf("impossible\n");
else printf("%d\n",ans[q]);
}
}
return 0;
}