description
N 个结点、M 个含K 个结点的完全子图构成一个奇怪的图,问从结点1 走
到结点N 最少需要经过多少个结点。
analysis
-
bfsbfsbfs
-
对于一个小完全图,不要暴力两两连边
-
其实我们把它连成一个菊花图,用中间的点连向这些点即可
-
然后跑一次宽搜
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define MAXN 110005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))
using namespace std;
vector<ll>v[MAXN];
ll n,m,k,ans=-1;
bool bz[MAXN];
ll val[MAXN];
struct node
{
ll x,dis;
}que[MAXN];
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline ll max(ll x,ll y)
{
return x>y?x:y;
}
O3 int main()
{
//freopen("T2.in","r",stdin);
n=read(),k=read(),m=read();
fo(i,1,n)val[i]=1;
fo(i,1,m)
{
val[n+i]=0;
fo(j,1,k)
{
ll x=read();
v[n+i].push_back(x),v[x].push_back(n+i);
}
}
memset(bz,1,sizeof(bz)),bz[1]=0;
ll l=0,r=1;que[1].x=1,que[1].dis=1;
while (l<r)
{
node now=que[++l];
if (now.x==n)
{
ans=now.dis;
break;
}
if (!v[now.x].size())continue;
fo(i,0,v[now.x].size()-1)if (bz[v[now.x][i]])
{
bz[v[now.x][i]]=0;
que[++r].x=v[now.x][i],que[r].dis=now.dis+val[v[now.x][i]];
}
}
printf("%lld\n",ans);
return 0;
}