【floyd倍增】[USACO 'NOV07][POJ3613]COW RELAYS

题目
分析:题目大意即在一个无向图中,询问从起点到终点,走n步的最短路。最多100条边,所以最多100个点,对点进行离散化。用floyd求最短路,因为floyd就是向中间插点(插点法)所以只需要做n次floyd,同时使用倍增来加速。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXM 100
int n,r[MAXM*2+1],u[MAXM*2+1],v[MAXM*2+1],wt[MAXM+1],m,s,t,nr;
typedef int matrix[MAXM+1][MAXM+1];
matrix ans;
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
void read(){
    Read(n),Read(m),Read(s),Read(t);
    memset(ans,0x3f,sizeof ans);
    int i;
    for(i=1;i<=m;i++){
        Read(wt[i]),Read(u[i]),Read(v[i]);
        r[(i<<1)-1]=u[i],r[i<<1]=v[i];
    }
    sort(r+1,r+m*2+1);
    nr=unique(r+1,r+m*2+1)-r-1;
    for(i=1;i<=m;i++){
        u[i]=lower_bound(r+1,r+nr+1,u[i])-r;
        v[i]=lower_bound(r+1,r+nr+1,v[i])-r;
        ans[u[i]][v[i]]=ans[v[i]][u[i]]=wt[i];
    }
}
void floyd(matrix a,matrix b,matrix c){
    int i,j,k;
    matrix d;
    memset(d,0x3f,sizeof d);
    for(k=1;k<=nr;k++)
        for(i=1;i<=nr;i++)
            for(j=1;j<=nr;j++)
                d[i][j]=min(d[i][j],a[i][k]+b[k][j]);
    memcpy(c,d,sizeof d);
}
void quick_pow(matrix a,int b,matrix c){
    matrix t,d;
    memset(d,0x3f,sizeof d);
    memcpy(t,a,sizeof t);
    for(int i=1;i<=nr;i++)
        d[i][i]=0;
    while(b){
        if(b&1)
            floyd(d,t,d);
        floyd(t,t,t);
        b>>=1;
    }
    memcpy(c,d,sizeof d);
}
int main()
{
    read();
    quick_pow(ans,n,ans);
    printf("%d\n",ans[lower_bound(r+1,r+nr+1,s)-r][lower_bound(r+1,r+nr+1,t)-r]);
}
posted @ 2016-01-25 23:18  outer_form  阅读(246)  评论(0编辑  收藏  举报