poj 3613

来源:互联网 发布:ps2017cc磨皮软件mac 编辑:程序博客网 时间:2024/06/08 09:39

     用矩阵来表示两个点之间走k步的最短路,然后快速幂。

#include <iostream>#include <cstdio>#include <cstring>#include <set>using namespace std;typedef long long ll;const int maxn=1e3+9;set <int> q;int a[maxn];int f[maxn][maxn];long long d[211][211];const long long inf=(ll)1111111111111;ll tt[211][211];void cal(ll a[211][211],ll b[211][211],ll c[211][211],int n){    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    tt[i][j]=inf;    for(int k=1;k<=n;k++)    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    if(b[i][k]+c[k][j]<tt[i][j])    tt[i][j]=b[i][k]+c[k][j];    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    a[i][j]=tt[i][j];}long long work(int m,int n,int from,int to){    long long ans[211][211];    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    ans[i][j]=inf;    ans[from][from]=0;    while(m)    {        if(m&1)        cal(ans,ans,d,n);        cal(d,d,d,n);        m/=2;    }    return ans[from][to];}int main(){    int n,t,s,e;//    scanf("%d %d %d %d",&n,&t,&s,&e);    while(scanf("%d %d %d %d",&n,&t,&s,&e)!=EOF)    {        memset(f,0,sizeof(f));        memset(d,11,sizeof(d));        q.clear();        for(int i=1,from,to,w;i<=t;i++)        {            scanf("%d %d %d",&w,&from,&to);            f[from][to]=f[to][from]=w;            q.insert(from);            q.insert(to);        }        int k=0;        for(set<int>:: iterator i=q.begin();i!=q.end();i++)        a[*i]=++k;        for(int i=1;i<=1000;i++)        for(int j=1;j<=1000;j++)        if(f[i][j])        d[a[i]][a[j]]=f[i][j];        cout<<work(n,k,a[s],a[e])<<endl;    }    return 0;}