The Shortest Path HDU - 2807
题面:有n < 80个点,每个点用一个m * m(m < 80)的矩阵表示,若a,b,c三个点满足a * b=c,则表示a到c有一条长度为1的单向边。
有q < 80次询问,每次询问x,y的最短路
关键在于如何处理这个矩阵。
思路在下面
这道题挺有意思的,得处理下矩阵的相乘,其实没必要弄得很复杂,直接暴力处理就行了。
floyd变形题,处理一下矩阵即可,因为数据不大,暴力求就行,也可以采取乘法优化。踩坑:注意A*B=B不能说明AB之间有边,在这里wa了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
#include<bits/stdc++.h> using namespace std; #define Debug(x) cout<<#x<<':'<<x<<endl #define INF 0x7fffffff typedef long long ll; typedef pair<ll,ll> P; const ll maxn=1e2+11; struct Node{ ll a[maxn][maxn]; }city[maxn]; ll gra[maxn][maxn]; ll n,m; void matirx(ll u,ll t){ ll mid[maxn][maxn]; for(ll i=1;i<=m;i++){ for(ll j=1;j<=m;j++){ mid[i][j]=0; for(ll k=1;k<=m;k++){ mid[i][j]+=city[u].a[i][k]*city[t].a[k][j]; } } } for(ll v=1;v<=n;v++){ if(v==u || v==t) continue; ll flag=1; for(ll i=1;i<=m;i++){ if(flag==0) break; for(ll j=1;j<=m;j++){ if(mid[i][j]!=city[v].a[i][j]){ flag=0;break; } } } if(flag) gra[u][v]=1; } } void floyd(){ for(ll k=1;k<=n;k++){ for(ll i=1;i<=n;i++){ for(ll j=1;j<=n;j++) gra[i][j]=min(gra[i][j],gra[i][k]+gra[k][j]); } } } int main(){ ios::sync_with_stdio(false); cin.tie(0); while(cin>>n>>m && (n||m)){ memset(gra,0x1f,sizeof(gra)); for(ll c=1;c<=n;c++){ for(ll i=1;i<=m;i++){ for(ll j=1;j<=m;j++) cin>>city[c].a[i][j]; } } for(ll i=1;i<=n;i++){ for(ll j=1;j<=n;j++){ if(i==j) continue; matirx(i,j); } } floyd(); ll q;cin>>q; for(ll i=1;i<=q;i++){ ll u,v;cin>>u>>v; if(gra[u][v]>1e9) cout<<"Sorry"<<endl; else cout<<gra[u][v]<<endl; } } return 0; }
|