题意:
给出一个带权图,问S到E恰好经过N个点的最短路。
题解:
floyd版的矩阵快速幂。好强大。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) typedef long long ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const ll MOD=10000; const int maxn=1005; int n; int ans[maxn][maxn],temp[maxn][maxn]; int a[maxn][maxn]; int id[maxn],mark[maxn]; int cmin(int& a,int b) { if(b<a) a=b; } void floyd(int x[][maxn],int y[][maxn]) { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cmin(temp[id[i]][id[j]],x[id[i]][id[k]]+y[id[k]][id[j]]); } void Copy(int x[][maxn],int y[][maxn]) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { x[id[i]][id[j]]=y[id[i]][id[j]]; y[id[i]][id[j]]=oo; } } void quick_pow(int x[][maxn],int k) { while(k) { if(k&1) { floyd(ans,x); Copy(ans,temp); } floyd(x,x); Copy(x,temp); k>>=1; } } int main() { int N,T,S,E; int u,v,w,cnt; while(scanf("%d %d %d %d",&N,&T,&S,&E)!=EOF) { n=0; memset(mark,0,sizeof mark); memset(temp,0x3f,sizeof temp); memset(ans,0x3f,sizeof ans); memset(a,0x3f,sizeof a); for(int i=0;i<maxn;i++) ans[i][i]=0; for(int i=1;i<=T;i++) { scanf("%d %d %d",&w,&u,&v); if(!mark[u]) { id[++n]=u; mark[u]=1; } if(!mark[v]) { id[++n]=v; mark[v]=1; } if(a[u][v]>w) a[u][v]=a[v][u]=w; } quick_pow(a,N); printf("%d\n",ans[S][E]); } return 0; } /* 2 6 6 4 11 4 6 4 4 8 8 4 9 6 6 8 2 6 9 3 8 9 */