备战蓝桥杯---图论应用1

news2024/11/15 9:12:40

目录

1.增加虚点建图:

2.抽象图的迪杰斯特拉:

3.用bitset优化弗洛伊德:

4.有向图的Prim/kruskal:


1.增加虚点建图:

我们当然可以每一层与上一层的点再连上一条边,但这样子边太多了超内存,我们可以对于每一层建立两个虚的中站,其中一个每一层的点到中站的距离=0,他连一条边与上面的站,权值为两层的距离,另一个向下(注意边都是单向边,否则会产生新的路径)。

2.抽象图的迪杰斯特拉:

每一个集合里如果互相连边的话边太多了,我们不妨把一个集合当成一个抽象的点,然后去跑迪杰斯特拉。因此我们只要记录每一个点属于的集合以及每一个集合中含有的点即可。

我们还是在枚举点,只不过我们要再多一个for来表示取出的集合,同时我们保证集合只被枚举一次,因为重复的集合不会使结果更优。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,m,t1[100010],ti,si,k;
vector<int> es[1000005];
vector<int> inque[100005];
int dis[2][100010];
bool vistuan[100010],visdian[100010];
int ans[100010];
struct node{
    int zhi,dian;
    bool operator<(const node &a) const{
        return zhi>a.zhi;
    }
};
priority_queue<node> q;
void dij(int s,int f){
    memset(vistuan,0,sizeof(vistuan));
    memset(visdian,0,sizeof(visdian));
    dis[f][s]=0;
    q.push({0,s});
    while(!q.empty()){
        node ck=q.top();
        q.pop();
        if(visdian[ck.dian]==1) continue;
        visdian[ck.dian]=1;
        for(int i=0;i<inque[ck.dian].size();i++){
            int j=inque[ck.dian][i];
            if(vistuan[j]==1) continue;
            vistuan[j]=1;
            for(int k=0;k<es[j].size();k++){
                int w=es[j][k];
                if(visdian[w]==1) continue;
                if(dis[f][w]>ck.zhi+t1[j]){
                    dis[f][w]=ck.zhi+t1[j];
                    q.push({dis[f][w],w});
                }
            }
        }
    }
}
signed main(){
    cin>>t;
    int i1=1;
    while(t--){
        scanf("%lld%lld",&n,&m);
        
        for(int i=1;i<=n;i++) inque[i].clear();
        memset(dis,0x7f7f7f7f,sizeof(dis));
        for(int i=1;i<=m;i++){
            es[i].clear();
            scanf("%lld%lld",&ti,&si);
            t1[i]=ti;
            for(int j=1;j<=si;j++){
                scanf("%lld",&k);
                es[i].push_back(k);
                inque[k].push_back(i);
            }
        }
        dij(1,0);
        dij(n,1);
        long long ans_tmp=1e18;
        int ans_len=0;
        for(int i=1;i<=n;i++)
        {
            if(max(dis[0][i],dis[1][i])<ans_tmp)
            {
                ans_tmp=max(dis[0][i],dis[1][i]);
                ans_len=0;
                ans[ans_len++]=i;
            }
            else if(max(dis[0][i],dis[1][i])==ans_tmp)
            {
                ans[ans_len++]=i;
            }
        }
           printf("Case #%d: ",i1++);
        if(ans_len==0||ans_tmp==1e18)
        {
            printf("Evil John\n");
        }
        else
        {
            printf("%lld\n",ans_tmp);
            for(int i=0;i<ans_len;i++)
            {
                printf("%lld",ans[i]);
                if(i==ans_len-1)
                    printf("\n");
                else
                    printf(" ");
            }
        }
    }
    }

3.用bitset优化弗洛伊德:

我们把>号表示成一条有向边即可。这样子我们就是求任意两点是否可以到,我们很容易想到弗洛伊德算法,但是这个复杂度铁超,我们发现,弗洛伊德还算出了最短距离,而我们只需要0/1,因此我们想到bitset优化,我们把每一个点能否到其他点记作01串,这样子当我们枚举中转使,只要或上中转的01串即可。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int dian,next;
}edge[100010];
bitset<1005> dp[1010];
int n,m,head[1010],cnt,x,y;
void merge(int x,int y){
    edge[++cnt].dian=y;
    edge[cnt].next=head[x];
    head[x]=cnt;
}
int main(){
    cin>>n>>m;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        merge(x,y);
        dp[x][y]=1;
    }
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            if(i==k) continue;
            if(dp[i][k]==0) continue;
            dp[i]|=dp[k];
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(dp[i][j]==1||dp[j][i]==1) continue;
            ans++;
        }
    }
    cout<<ans;
}

4.有向图的Prim/kruskal:

显然,我们先建个由高度决定的有向边,我们再跑一个DFS,记录哪个点可否到达,这样子,我们就可以得到类似于树的结构,假如他是无向边,我们就是求个最小生成树,但是因为是有向边,我们不可以直接跑这两个算法,我们不妨想想是为什么?

其实,问题就在于你无法保证那条连的边是可以按照正确方向走的,或者说,按照他走可能走不通,而这是由高度造成的,于是我们可以按照高度,从上到下建立关系,我们不妨先看1,2层,当他们建好时再考虑第3层,依次类推即可。

如果用Prim算法,我们只需先按照高度排序即可。

如果用kruskal算法,我们在存边时在记录下两者中较低的高度sort即可。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,h[100010],vis[100010],u,v,k,cnt,fa[100010];
struct node{
    int x,y,z,h;
}bian[1000100];
vector<int> edge[1000100];
void dfs(int ck){
    cnt++;
    vis[ck]=1;
    for(int i=0;i<edge[ck].size();i++){
        int yy=edge[ck][i];
        if(vis[yy]==1) continue;
        dfs(yy);
    }
    return;
}
bool cmp(node a,node b){
    if(a.h==b.h) return a.z<b.z;
    return a.h>b.h;
}
int find(int x){
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&h[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&k);
        if(h[u]>h[v]) edge[u].push_back(v);
        else if(h[u]<h[v]) edge[v].push_back(u);
        else{
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        bian[i].x=u;
        bian[i].y=v;
        bian[i].z=k;
        bian[i].h=min(h[u],h[v]);
    }
    dfs(1);
    cout<<cnt<<" ";
    long long ans=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(bian+1,bian+m+1,cmp);
    for(int i=1;i<=m;i++){
        int xx=bian[i].x;
        int yy=bian[i].y;
        if(vis[xx]==0||vis[yy]==0) continue;
        int xxx=find(xx);
        int yyy=find(yy);
        if(xxx==yyy) continue;
        ans+=bian[i].z;
        fa[xxx]=yyy;
    }
    cout<<ans;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1490107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【学习心得】网站运行时间轴(爬虫逆向)

一、网站运行时间轴 掌握网站运行时间轴&#xff0c;有助于我们对“请求参数加密”和“响应数据加密”这两种反爬手段的深入理解。 二、从网站运行的时间轴角度来理解两种反爬手段 1、加载HTML&#xff1a; 这是浏览器访问网站时的第一步&#xff0c;服务器会返回基础…

6.Java---二维数组

打印二维数组的每个元素 上图所示,我们打印的时候将行列的数字写死,但是实际上如果这个数组有很多元素我们还要一个个数数嘛?这不是很占用我们的时间啦!因此引出下文. 代码精进 二维数组的每个元素是一个一维数组 打印二维数组的法2 打印出的格式如下: 不规则的二维数组…

LeetCode每日一题之 复写0

目录 题目介绍&#xff1a; 算法原理&#xff1a; 特殊位置处理&#xff1a; 代码实现&#xff1a; 题目介绍&#xff1a; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 算法原理&#xff1a; 这种对数组元素进行修改&#xff0c;移动的题目我们仍然可以…

使用Android Native Hook技术解决VLC播放器闪退的问题

文章目录 1.概述2.问题描述3.问题分析4.问题解决5.总结 1.概述 在做公司的一个TOB的需求时&#xff0c;发现调起Unity提供的3D播放器播放网络在线视频时闪退了&#xff0c;然后就拉着相关部门的人一起分析问题&#xff0c;最后定位到是VLC里面用到的系统日志打印函数在部分的系…

《UE5_C++多人TPS完整教程》学习笔记26 ——《P27 在线会话测试(Testing An Online Session)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P27 在线会话测试&#xff08;Testing An Online Session&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff0…

二分查找是偏爱细节的魔鬼

大家好&#xff0c;我是 方圆。二分查找本质上是一个规模退化且固定规模减小一半的分治算法&#xff0c;它的 思路很简单&#xff0c;但细节是魔鬼。通常我们会认为二分查找的应用场景是数组有序&#xff08;单调&#xff09;&#xff0c;但实际上它也能在无序数组中应用&#…

【轻快图片管理系统】-系统预览截图

在线体验 如果你觉得项目不错&#xff0c;还望动动你的手指给点点star&#xff0c;让更多人看到优秀的项目&#xff01;&#xff01;&#xff01; 为了便于大家在线体验&#xff0c;本系统提供了演示地址&#xff0c;可以通过下面的演示地址和账号进行登录体验系统功能。 演示…

leetcode 热题 100_和为 K 的子数组

题解一&#xff1a; 前缀和数组哈希表&#xff1a;可以计算所有子数组之和暴力求解&#xff0c;但复杂度太高。对于子数组求和的过程&#xff0c;我们可以采用前缀和数组进行优化&#xff0c;前缀和数组中pre[index]代表nums[0]~nusm[index]之和&#xff0c;当我们要计算子数组…

【树】【异或】【深度优先】【DFS时间戳】2322. 从树中删除边的最小分数

作者推荐 【二分查找】【C算法】378. 有序矩阵中第 K 小的元素 涉及知识点 树 异或 DFS时间戳 LeetCode2322. 从树中删除边的最小分数 存在一棵无向连通树&#xff0c;树中有编号从 0 到 n - 1 的 n 个节点&#xff0c; 以及 n - 1 条边。 给你一个下标从 0 开始的整数数组…

Vscode连接外部虚拟环境

如果vscode工程目录里面有一个超级大的虚拟环境文件夹&#xff0c;怎么说都不是一件优雅的事&#xff0c;因此我们希望这个虚拟环境在工程目录外部&#xff0c;我们开始&#xff1a; 1. 复制虚拟环境目录路径&#xff1a;E:\envs\test 2. 在vscode中打开文件夹&#xff0c;CT…

全球首个隐私计算一体机国际标准发布 蚂蚁摩斯参与编制

近日&#xff0c;IEEE 标准协会&#xff08;IEEE-SA&#xff09;正式发布并推行了全球首个隐私计算一体机国际标准《隐私计算一体机技术要求》&#xff08;IEEE 3156-2023&#xff09;。该标准由蚂蚁集团推动&#xff0c;中科院信息工程研究所、北京交通大学、中国信息通信研究…

第十六天-爬虫selenium库

目录 1.介绍 2.使用 selenium 1.安装 2.使用 1.测试打开网页&#xff0c;抓取雷速体育日职乙信息 2.通过xpath查找 3.输入文本框内容 send_keys 4.点击事件 click 5.获取网页源码&#xff1a; 6.获取cookies 7.seleniumt提供元素定位方式&#xff1a;8种 8.控制浏览…

第一弹:Flutter安装和配置

目标&#xff1a; 1&#xff09;配置Flutter开发环境 2&#xff09;创建第一个Flutter Demo项目 Flutter中文开发者网站&#xff1a; https://flutter.cn/ 一、配置Flutter开发环境 Flutter开发环境已经提供集成IDE开发环境&#xff0c;因此需要配置开发环境的时候&#xf…

Gitlab 安装部署

目录 1、Jenkins 结合 Gitlab 构建 CI/CD 环境 CI/CD 介绍 CI/CD 流程 Jenkins 简介 GitLab 简介 项目部署方式 CI系统的工作流程 2、搭建 GitLab 安装 GitLab 配置 GitLab 修改root密码 访问 GitLab 开机自启 3、使用 GitLab 管理 GitLab 关闭 GitLab 注册功能…

Git分支补充

我们在合并分支时并不总是一帆风顺&#xff0c;有些时候也会遇到“合并冲突”的问题。 下面我们来还原一下&#xff1a; 创建分支dev $ git checkout -b dev 切换到一个新分支 dev $ git branch * devmaster我们将 text.txt 内容改为 欢迎关注CSDNkeduo并将修改的内容提交到 d…

【Oracle Database】如何远程连接服务器、创建用户、从本地dmp导入表

C:\Users\test>imp test/123456ip/orcl:1521 fileE:\db.dmp tablestable1,table2Import: Release 11.2.0.3.0 - Production on 星期一 3月 4 12:59:09 2024Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.IMP-00058: 遇到 ORACLE 错误 1263…

EdgeX Foundry 安全模式安装部署

文章目录 一、安装准备1.官方文档2. 克隆服务器3.安装 Docker4.安装 docker-compose 二、安装部署1.docker-comepse2.启动 EdgeX Foundry3.访问 UI3.1. consul3.2. EdgeX Console EdgeX Foundry # EdgeX Foundryhttps://iothub.org.cn/docs/edgex/ https://iothub.org.cn/docs…

CUDA学习笔记02:测试程序hello world

参考资料 Win10下在VS2019中配置使用CUDA进行加速的C项目 &#xff08;配置.h文件&#xff0c;.dll以及.lib文件等&#xff09;_vs2019 cuda-CSDN博客 配置流程 1. 新建一个一般的项目 2. 项目建好后&#xff0c;在项目里添加.cu测试文件 测试的.cu文件命名为cuda_utils.cu&…

bert 相似度任务训练简单版本,faiss 寻找相似 topk

目录 任务 代码 train.py predit.py faiss 最相似的 topk 数 任务 使用 bert-base-chinese 训练相似度任务&#xff0c;参考&#xff1a;微调BERT模型实现相似性判断 - 知乎 参考他上面代码&#xff0c;他使用的是 BertForNextSentencePrediction 模型&#xff0c;Bert…

在idea中用模板骨架初始创建maven管理的web项目时没有src有关的目录的解决方案

一.问题如下 二.解决方法 首先关闭当前项目&#xff0c;接着修改全局设置&#xff0c;重新创建项目 在VM Options中添加"-DarchetypeCataloginternal"&#xff0c;点击ok保存 点击创建&#xff0c;如果创建成功没报错且有src&#xff0c;就ok了。 当然如果出现以下…