首页 > 其他分享 >分层图练习

分层图练习

时间:2024-04-23 22:12:08浏览次数:21  
标签:pq emplace int 练习 分层 vct take dis

P4568 [JLOI2011] 飞行路线 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

//////////////////////////////////////////////////////法一:分层图
int n,m,k;
int s,t;
const int inf=0x3f3f3f3f;
vector<pair<int,int>> vct[10004*12];   //开多层,一定要开大点!!10004*11都是RE的
priority_queue<pair<int,int>> pq;
int dis[10004*12],vis[10004*12];
void dijkstr(int s){
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    pq.emplace(0,s);
    while(pq.size()){
        int from=pq.top().second;
        pq.pop();
        if(vis[from]) continue;
        vis[from]=1;
        for(auto v:vct[from]){
            int to=v.first,weight=v.second;
            if(dis[to]>dis[from]+weight){
                dis[to]=dis[from]+weight;
                pq.emplace(-dis[to],to);
            }
        }
    }
}
void solve(){
    cin>>n>>m>>k;
    cin>>s>>t;
    for(int i=1;i<=m;i++){
        int u,v,w; cin>>u>>v>>w;
        for(int j=0;j<=k;j++){           //重边不必处理--key:j=[0,k]--到k是因为k的本层要建图,但是k不需要连向k+1层,连了也没wa。
            vct[u+j*n].emplace_back(v+j*n,w);           //本层是双向的
            vct[v+j*n].emplace_back(u+j*n,w);
            if(j!=k) vct[u+j*n].emplace_back(v+(j+1)*n,0);         //下层的单向的
            if(j!=k) vct[v+j*n].emplace_back(u+(j+1)*n,0);
        }
    }
    dijkstr(s);
    int ans=INT_MAX;
    for(int i=0;i<=k;i++)
        ans=min(ans,dis[t+i*n]);
    cout<<ans;
}
////////////////////////////////////////////////////法二:dp
int n,m,k;
int s,t;
typedef struct myp{
    int d,node;
    int t;
    friend bool operator < (const myp a,const myp b){
        return a.d>b.d;         //大于号才是!!小根堆!!!
    }
}myp;
const int inf=0x3f3f3f3f;
vector<pair<int,int>> vct[10004];
priority_queue<myp> pq;
int dis[10004][15],vis[10004][15];
void dijkstr(int s){
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s][0]=0;
    pq.emplace((myp){0,s,0});
    while(pq.size()){
        int from=pq.top().node;
        int take=pq.top().t;
        pq.pop();
        if(vis[from][take]) continue;
        vis[from][take]=1;
        for(auto v:vct[from]){
            int to=v.first,weight=v.second;
            if(take+1<=k){
                if(dis[to][take+1]>dis[from][take]){
                    dis[to][take+1]=dis[from][take];
                    pq.emplace((myp){dis[to][take+1],to,take+1});
                }
            }
            if(dis[to][take]>dis[from][take]+weight){
                dis[to][take]=dis[from][take]+weight;
                pq.emplace((myp){dis[to][take],to,take});
            }
        }
    }
}
void solve(){
    cin>>n>>m>>k;
    cin>>s>>t;
    for(int i=1;i<=m;i++){
        int u,v,w; cin>>u>>v>>w;
        vct[u].emplace_back(v,w);
        vct[v].emplace_back(u,w);
    }
    dijkstr(s);
    int ans=INT_MAX;
    //hack数据--不能单纯输出dis[t][k],类似限高杆,不一定用完免费的会更值当!!!所以要在[0,k]中取最小值。
    //k>m0,m0为s到t需要最少的边,如果要用完k,可能会导致跑多余的路程.
    for(int i=0;i<=k;i++) ans=min(ans,dis[t][i]);
    cout<<ans;
}

P8724 [蓝桥杯 2020 省 AB3] 限高杆 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

////////////////////////////////////////////法一:分层图
int n,m;
const int inf=0x3f3f3f3f;
vector<pair<int,int>> vct[30004];
priority_queue<pair<int,int>> pq;
int dis[30004],vis[30004];
void dijkstr(int s){
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    pq.emplace(0,s);
    while(pq.size()){
        int from=pq.top().second;
        pq.pop();
        if(vis[from]) continue;
        vis[from]=1;
        for(auto v:vct[from]){
            int to=v.first,weight=v.second;
            if(dis[to]>dis[from]+weight){
                dis[to]=dis[from]+weight;
                pq.emplace(-dis[to],to);
            }
        }
    }
}
void solve(){               
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v,w,c; cin>>u>>v>>w>>c;
        //用以下方式建一个立体的三层图,跑正常的dijkstra即可。恢复一条边的最短距离为dis[2*n];恢复两条边的最短距离为dis[3*n];
        //此题恢复的边一定会用上那条边,不一定恢复两条边会比恢复一条边短,或比不恢复边短。取min即可。
        if(c==0){               //没有障碍,三层都在本层正常建边
            vct[u].emplace_back(v,w);  //第一层
            vct[v].emplace_back(u,w);
            vct[u+n].emplace_back(v+n,w);  //第二层
            vct[v+n].emplace_back(u+n,w);
            vct[u+2*n].emplace_back(v+2*n,w);  //第三层
            vct[v+2*n].emplace_back(u+2*n,w);
        }
        else{       //有障碍,第一层连向第二层,第二层连向第三层。
//            vct[u].emplace_back(v+n,w);   //这4行是错的。
//            vct[v+n].emplace_back(u,w);
//            vct[u+n].emplace_back(v+2*n,w);
//            vct[v+2*n].emplace_back(u+n,w);
            vct[u].emplace_back(v+n,w);   //单向的!!一层向下一层!!,否则可能会从下层更新上层的点
            vct[v].emplace_back(u+n,w);
            vct[u+n].emplace_back(v+2*n,w);
            vct[v+n].emplace_back(u+2*n,w);
        }
    }
    dijkstr(1);
    cout<<dis[n]-min({dis[n],dis[2*n],dis[3*n]});   //不一定恢复的边越多越短!直接取三个的最小值准没错!!
}
/////////////////////////////////////////////////法二:dp
int n,m;
typedef struct myp1{
    int v,w,typ;
}myp1;
typedef struct myp2{
    int d,node,take;
    friend bool operator <(const myp2 a,const myp2 b){    //只能重载小于号!!
        return a.d>b.d;      //按d的从小到大排序
    }
}mpy2;
const int inf=0x3f3f3f3f;
vector<myp1> vct[10004];
priority_queue<myp2> pq;
//priority_queue<pair<int,pair<int,int>>> pq;
int dis[10004][3],vis[10004][3];    //dis[i][j]:已经用了j次免费机会的情况下,到达i的最小距离
void dijkstra(int s){
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[s][0]=0;
    pq.emplace((myp2){0,s,0});
    while(pq.size()){
        int from=pq.top().node;
        int take=pq.top().take;
        pq.pop();
        if(vis[from][take]) continue;
        vis[from][take]=1;
        for(auto v:vct[from]){
            int to=v.v,weight=v.w,typ=v.typ;
            if(take+typ>2) continue;
            if(dis[to][take+typ]>dis[from][take]+weight){       //dis[to][take+typ] 从 dis[from][take]+weight转移!!
                dis[to][take+typ]=dis[from][take]+weight;
                pq.emplace(myp2{dis[to][take+typ],to,take+typ});
            }
        }
    }
}
void solve(){         //不建分层图,用动态规划思想.
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v,w,t; cin>>u>>v>>w>>t;
        vct[u].emplace_back((myp1){v,w,t});
        vct[v].emplace_back((myp1){u,w,t});
    }
    dijkstra(1);
    cout<<dis[n][0]-min({dis[n][0],dis[n][1],dis[n][2]});     //不一定恢复的边越多越短!直接取三个的最小值准没错!!
}

ps:似乎分层图都可以用dp来做。

标签:pq,emplace,int,练习,分层,vct,take,dis
From: https://www.cnblogs.com/ouhq/p/18153876

相关文章

  • 数据结构的练习day2(未完待续)
    数据结构线性结构之单向循环链表的基本操作/***********************************************************************************************************设计单向循环链表的接口****Copyright(c)[email protected]......
  • 【图论】最短路练习——P1629邮递员送信
    邮递员送信题目描述有一个邮递员要送东西,邮局在节点\(1\)。他总共要送\(n-1\)样东西,其目的地分别是节点\(2\)到节点\(n\)。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有\(m\)条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完......
  • FasterViT:英伟达提出分层注意力,构造高吞吐CNN-ViT混合网络 | ICLR 2024
    论文设计了新的CNN-ViT混合神经网络FasterViT,重点关注计算机视觉应用的图像吞吐能力。FasterViT结合CNN的局部特征学习的特性和ViT的全局建模特性,引入分层注意力(HAT)方法在降低计算成本的同时增加窗口间的交互。在包括分类、对象检测和分割各种CV任务上,FasterViT在精度与图像吞吐......
  • 前端【uniapp】06-uniapp【练习项目 · 神领物流】【任务【交付】【回车登记】【已完
    uni-app(神领物流)项目实战学习目标:能够独立完成回交付、回车登记的功能能够自定义回车登记交互组件能够使用Pinia实现组件间数据共享能够打包发布H5、小程序和App项目应用能够配置App的图标及启动屏幕一、【神领物流】任务1、交付司机在将货物运达目......
  • 顺序表和链表的练习题
    顺序表题目一:题目分析:该题目需要先对顺序表进行遍历至元素x正确插入位置,再对顺序表完成插入操作。因此涉及到for循环与if语句的使用代码实现/********************************************************************** name : SequenceList_insert* function:实现插......
  • 数据结构的练习day1
    链表只能一个一个的遍历,不能通过随机访问来获取节点链表的地址是并要求连续的,是通过内部的指针来进行联系的/***************************************************************************************************************Copyright(c)2023-2024......
  • 34.c语言数组练习题(牛客网)
    先打个广告哈哈哈牛客网练编程题不错不错哦冒泡排序必须必须必须会#include<stdio.h>voidsort(intarr[],intn){//外层循环for(inti=0;i<n-1;++i){intflag=1;//假设flag=1就是已经排序好的//内层循环for(intj=0;......
  • rhce练习题容易错的地方
    rhce练习题里容易错的地方使用导航器的时候,ssh连接因为导航器是一个工具,生成一个容器,在容器里面运行playbook安装软件包的时候,多个软件包使用循环looploop的格式-hosts:NODE1tasks:-name:installphpansible.builtin.yum:name:"{{ite......
  • 前端【uniapp】03-uniapp【练习项目 · 神领物流】
    uni-app(神领物流)项目实战学习目标:能够对Pinia进行初始化操作掌握创建Store及数据操作的步骤能够对Pinia数据进行持久化的处理掌握uniForm表单验证的使用方法能够根据业务需求配置请求/响应拦截器一、【神领物流】项目启动本节的主要任务是获取项......
  • 对于前三次的pta题集练习,由于我的偷懒和迟钝,有许多部分没有完成,但在此我还是对题目集
    第一道大题题目信息7-1答题判题程序-1分数50作者蔡轲单位南昌航空大学设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。输入格式:程序输入信息分三部分:1、题目数量格式:整数数值,若超过1位最高位不能为0,......