题目:我是超链接
题解:
一个SPFA版本的。看看这个2^k就知道是倍增,一开始想用类似求lca的方法,但是发现这样一个远度的只能连一个点(只有一个爸爸),但其实可以连到好多点,我们考虑用Floyd,f[l][i][j]表示走2^l i可以走到j,那读入就是f[0][i][j],然后求最短路就ok了。可以用Floyd,也可以SPFA
代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#define sz 32
using namespace std;
int h[55],mi[sz],tot,nxt[2500],point[55],v[2500],f[sz][55][55],dis[55];
bool c[55];
void addline(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
int main()
{
int n,i,j,m,l,k;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
f[0][x][y]=1;
}
for (l=1;l<sz;l++)
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
f[l][i][j]=f[l][i][j] || (f[l-1][i][k]&&f[l-1][k][j]);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
for (l=0;l<sz;l++)
if (f[l][i][j])
{addline(i,j);break;}
memset(dis,0x7f,sizeof(dis));
queue <int> q;
q.push(1);
dis[1]=0;
while (!q.empty())
{
int now=q.front(); q.pop(); c[now]=0;
for (int i=point[now];i;i=nxt[i])
if (dis[v[i]]>dis[now]+1)
{
dis[v[i]]=dis[now]+1;
if (!c[v[i]])
{
c[v[i]]=true;
q.push(v[i]);
}
}
}
printf("%d",dis[n]);
}