最短路+线段树 空间宝石
题目
思路
- 我们定义矩阵结构体来存放每一个优先级下的图的情况(反正点只有9个),读入数据后,对每一个矩阵跑一遍Floyd(四层循环),求出当前优先级下的图中的联通情况;
- 定义矩阵乘法的结果为在前一个优先级矩阵添加后一个优先级矩阵后图的联通情况(有亿点像矩阵乘法)
Matrix operator * (const Matrix &r)const {
Matrix res;
for(int k=0;k<9;k++)
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
res.a[i][j]=min(res.a[i][j],a[i][k]+r.a[k][j]);
return res;
}
- 建树:把每一个矩阵挂在线段树上,父节点存放左右矩阵相乘的结果
tree[rt]=tree[rt<<1]*tree[rt<<1|1];
- 查询:正常的区间查询
Matrix query(int rt,int l,int r,int s,int t){
if(s<=l&&t>=r)return tree[rt];
int mid=(l+r)>>1;
if(t<=mid)return query(rt<<1,l,mid,s,t);
if(s>mid)return query(rt<<1|1,mid+1,r,s,t);
return query(rt<<1,l,mid,s,t)*query(rt<<1|1,mid+1,r,s,t);
}
- 细节:记得先把给出的优先级排序一下,先处理优先级小的,再处理大的
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2000+10;
struct Matrix{
int a[10][10];
Matrix(){
memset(a,0x3f,sizeof(a));
for(int i=0;i<9;i++)a[i][i]=0;
}
Matrix operator * (const Matrix &r)const {
Matrix res;
for(int k=0;k<9;k++)
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
res.a[i][j]=min(res.a[i][j],a[i][k]+r.a[k][j]);
return res;
}
}tree[N<<2],mp[N];
struct ques{
int q1,q2;
}qq[10000+10];
bool com(ques a,ques b){
return a.q1<b.q1;
}
int Max=0;
void build(int rt,int l ,int r){
if(l==r){
tree[rt]=mp[l];
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tree[rt]=tree[rt<<1]*tree[rt<<1|1];
}
Matrix query(int rt,int l,int r,int s,int t){
if(s<=l&&t>=r)return tree[rt];
int mid=(l+r)>>1;
if(t<=mid)return query(rt<<1,l,mid,s,t);
if(s>mid)return query(rt<<1|1,mid+1,r,s,t);
return query(rt<<1,l,mid,s,t)*query(rt<<1|1,mid+1,r,s,t);
}
int main(){
int n,S;
scanf("%d%d",&n,&S);
for(int i=1;i<=n;i++){
int p,x,y,z;
scanf("%d%d%d%d",&p,&x,&y,&z);
if(mp[p].a[x][y]>=z)mp[p].a[x][y]=z;
Max=max(Max,p);
}
for(int vv=1;vv<=Max;vv++){
for(int k=0;k<9;k++){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
mp[vv].a[i][j]=min(mp[vv].a[i][j],mp[vv].a[i][k]+mp[vv].a[k][j]);
}
}
}
}
build(1,1,Max);
int q;scanf("%d",&q);
while(q--){
int si,ti,num;
scanf("%d%d%d",&si,&ti,&num);
Matrix temp;
for(int i=1;i<=num;i++){
scanf("%d%d",&qq[i].q1,&qq[i].q2);
}
sort(qq+1,qq+1+num,com);
for(int i=1;i<=num;i++){
temp=temp*query(1,1,Max,qq[i].q1,qq[i].q2);
}
if(temp.a[si][ti]!=0x3f3f3f3f){
printf("%d\n",temp.a[si][ti]);
}
else{
printf("-1\n");
}
}
}
好像好久没有正经的写一篇题解了)