【题解】P1613跑路

【题解】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;
}




原文地址:https://www.cnblogs.com/winlere/p/10333914.html