【luogu1613】跑路(倍增)

题目:我是超链接

题解:

一个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]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值