AcWing345 牛站(floyd+倍增)

设计状态为走了k步,从i-j的最短路,由于加法满足结合律,因此可以用倍增来优化逼近n

这样可以log复杂度逼近,代码与floyd相似,但是状态的定义完全不同,本题还需要离散化一下,因为原数太大

#include<bits/stdc++.h>
using namespace std;
const int N=210;
int g[N][N];
int res[N][N];
int n,t,s,e;
int cnt;
void mul(int c[][N],int a[][N],int b[][N]){
    int tmp[N][N];
    memset(tmp,0x3f,sizeof tmp);
    int i,j,k;
    for(k=1;k<=cnt;k++){
        for(i=1;i<=cnt;i++){
            for(j=1;j<=cnt;j++){
                tmp[i][j]=min(tmp[i][j],a[i][k]+b[k][j]);
            }
        }
    }
    memcpy(c,tmp,sizeof tmp);
}
void qmi(){
    memset(res,0x3f,sizeof res);
    for(int i=1;i<N;i++)
    res[i][i]=0;
    while(n){
        if(n&1){
            mul(res,res,g);
        }
        mul(g,g,g);
        n>>=1;
    }
}
int main(){
    memset(g,0x3f,sizeof g);
    cin>>n>>t>>s>>e;
    int i;
    map<int,int> id;
     cnt=1;
    if(!id.count(s))
        id[s]=cnt++;
    if(!id.count(e))
    id[e]=cnt++;
    s=id[s];
    e=id[e];
    for(i=1;i<=t;i++){
        int a,b,c;
        scanf("%d%d%d",&c,&a,&b);
        if(!id.count(a)) id[a]=cnt++;
        if(!id.count(b)) id[b]=cnt++;
        a=id[a],b=id[b];
        g[a][b]=g[b][a]=min(g[a][b],c);
    }
    cnt--;
    qmi();
    printf("%d\n",res[s][e]);
}
View Code

 

posted @ 2020-05-05 21:41  朝暮不思  阅读(185)  评论(0编辑  收藏  举报