• 最短路+线段树 空间宝石


    题目

    思路

    • 我们定义矩阵结构体来存放每一个优先级下的图的情况(反正点只有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
    ",temp.a[si][ti]);
    		}
    		else{
    			printf("-1
    ");
    		}
    	}
    }
    
    
    
    

    好像好久没有正经的写一篇题解了)

  • 相关阅读:
    DTV_SI 汇总 & 兼谈LCN
    Java 泛型 五:泛型与数组
    Java 泛型 四 基本用法与类型擦除
    Java 泛型 三
    Java 泛型 二
    Java 泛型 一
    Java集合类解析 ***
    Java 集合类
    MySQL入门01-MySQL源码安装
    如何彻底杀掉不良用户会话
  • 原文地址:https://www.cnblogs.com/soda-ma/p/13435163.html
Copyright © 2020-2023  润新知