题意:
给出一个带权图,问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
*/