【题解】P1613 鸽王跑路
一道思维好题!
考虑(2^k)的传递性。直接64遍(floyd)求所有(2^k)的路径,转移方程是
(dp(i,j,k)=[dp[i][t][k-1])&&(dp[t][j]][k-1])
有了这个之后先(O(n^3))预处理,然后根据这样的数组直接建边跑最短路即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<bitset>
#include<vector>
#include<map>
#include<ctime>
#include<cstdlib>
#include<set>
#include<bitset>
#include<stack>
#include<list>
#include<cmath>
using namespace std;
#define RP(t,a,b) for(register int (t)=(a),edd_=(b);t<=edd_;++t)
#define DRP(t,a,b) for(register int (t)=(a),edd_=(b);t>=edd_;--t)
#define ERP(t,a) for(int t=head[(a)];t;t=e[t].nx)
#define Max(a,b) ((a)<(b)?(b):(a))
#define Min(a,b) ((a)<(b)?(a):(b))
#define TMP template<class ccf>
typedef long long ll;
TMP inline ccf qr(ccf k){
char c=getchar();
ccf x=0;
int q=1;
while(c<48||c>57)
q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)
x=x*10+c-48,c=getchar();
if(q==-1)
x=-x;
return x;
}
int m,n;
const int maxn=55;
bool d[maxn][maxn][71];
inline void add(int fr,int to){
d[fr][to][0]=1;
}
const int maxe=51*51*15;
struct E{
int to,nx;
}e[maxe];
int head[maxn];
int cnt;
inline void add2(int fr,int to){
e[++cnt]=(E){to,head[fr]};
head[fr]=cnt;
}
int t1,t2;
queue< int > q;
int ans[maxn];
bool in[maxn];
const int inf=0x3f3f3f3f;
inline void spfa(){
RP(t,1,n)
ans[t]=inf;
ans[1]=0;
in[1]=1;
q.push(1);
while(!q.empty()){
t1=q.front();
q.pop();
in[t1]=0;
ERP(t,t1){
if(ans[e[t].to]>ans[t1]+1){
ans[e[t].to]=ans[t1]+1;
if(!in[e[t].to])
q.push(e[t].to);
in[e[t].to]=1;
}
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
n=qr(1);
m=qr(1);
RP(t,1,m){
t1=qr(1);
t2=qr(1);
add(t1,t2);
}
RP(k,0,65){
RP(i,1,n){
RP(t,1,n){
RP(f,1,n){
d[t][f][k+1]|=(d[t][i][k]&&d[i][f][k]);
}
}
}
}
RP(t,1,n){
RP(i,1,n){
if(t==i)
continue;
RP(k,0,65){
if(d[t][i][k]){
add2(t,i);
break;
}
}
}
}
spfa();
cout<<ans[n]<<endl;
return 0;
}