CCF-CSP真题《202305-4 电力网络》思路+python,c++满分题解

news2024/12/23 16:38:39

 想查看其他题的真题及题解的同学可以前往查看:CCF-CSP真题附题解大全

试题编号:202305-4
试题名称:电力网络
时间限制:1.0s
内存限制:512.0MB
问题描述:

问题描述

西西艾弗岛电力公司需要修建一套电网对岛上的众多城镇进行供电。电网设施包括建造在城镇中的变电站,与建造在城镇间的输电线路。根据前期的考察结果,电力公司已经确定了哪些城镇之间需要建造输电线路,以使得所有城镇能够被连接成一个电力网络。每座城镇只需要建造一个变电站,却都向电力公司提供了多个建造候选地址。对于每个城镇,不同候选地址的变电站造价不同;对于城镇间的输电线路,其造价也会随着两端变电站的候选地址的变化而变化。因此,电力公司想要知道,在所有候选地址的组合中,电网的总造价(变电站造价加上输电线路造价)最低是多少。

输入格式

从标准输入读入数据。

输入的第一行包括三个正整数 N、M、K。表示一共有 N 座城镇,需要建造 M 条输电线路,每座城镇都提供了 K 个变电站候选地址。

接下来输入 N 行,每行表示一个城镇。每行包含 K 个整数,表示该城镇不同候选地址的变电站造价。

接下来 M 行,每行表示一条输电线路,包含 K2+2 个整数。前两个整数表示该输电线路两端的城镇,范围是 [0, N)。第三个整数开始是大小为 K×K 的矩阵 T 的行主序存储形式。Tij 表示当输电线路的第一个端点选择候选地址 i,第二个端点选择候选地址 j 时的线路造价。

输出格式

输出到标准输出中。

输出包含一行,这一行有一个整数,表示电网的最低总造价。

样例输入

2 1 2
1 2
3 4
0 1 1 2 3 4

Data

样例输出

5

Data

样例说明

城镇 0 与城镇 1 均选择了 0 号地址建造变电站。

子任务

对于全部数据,保证由城镇与输电线路构成的图是无向无重边无自环的连通图,保证单个变电站与单条线路的造价均不超过 1000。

对于 20% 的数据,保证 N≤6,K≤10。

对于另外 20% 的数据,保证 N≤104,K≤10,M=N−1。

对于另外 20% 的数据,保证 N≤104,K≤10,M=N。

对于另外 20% 的数据,保证 N≤104,K≤10。图中存在两个节点 S、D,保证全图去除 D 节点和与 D 节点相连的边后,可以构成以 S 节点为根的一棵树,而且所有与 D 相连的节点都属于这棵树的叶子节点。

对于最后 20% 的数据,保证 N≤104,K≤10,且度数大于 2 的节点数量 ≤6。

真题来源:电力网络

感兴趣的同学可以如此编码进去进行练习提交

c++ 80分题解: 

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
 
const LL inf = 1e18;
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n, k, m;
    cin >> n >> m >> k;
    vector<vector<int>> pcost(n, vector<int>(k));
    for(auto &i : pcost)
        for(auto &j : i)
            cin >> j;
    vector<vector<array<int, 2>>> edge(n);
    vector<array<int, 2>> edges(m);
    vector<vector<int>> ecost(m, vector<int>(k * k));
    for(int i = 0; i < m; ++ i){
        int u, v;
        cin >> u >> v;
        edges[i] = {u, v};
        edge[u].push_back({v, i});
        edge[v].push_back({u, i});
        for(auto &j : ecost[i])
            cin >> j;
    }
    if (n <= 6 && k <= 10){
        vector<int> used(n);
        LL ans = inf;
        LL tmp = 0;
        function<void(int)> dfs = [&](int x){
            if (x == n){
                LL back = tmp;
                for(int i = 0; i < m; ++ i){
                    int u = edges[i][0], v = edges[i][1], id = i;
                    int r = used[u] * k + used[v];
                    tmp += ecost[id][r];
                }
                ans = min(ans, tmp);
                tmp = back;
                return;
            }
            for(int i = 0; i < k; ++ i){
                tmp += pcost[x][i];
                used[x] = i;
                dfs(x + 1);
                tmp -= pcost[x][i];
            }
        };
        dfs(0);
        cout << ans << '\n';
    }else if (m == n - 1){
        vector<vector<LL>> dp(n, vector<LL>(k, 0));
        function<void(int, int)> dfs = [&](int u, int fa){
            for(auto e : edge[u]){
                int v = e[0], id = e[1];
                if (v == fa)
                    continue;
                dfs(v, u);
                for(int i = 0; i < k; ++ i){
                    LL tmp = inf;
                    for(int j = 0; j < k; ++ j){
                        int L = i, R = j;
                        if (u != edges[id][0])
                            swap(L, R);
                        int r = L * k + R;
                        tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
                    }
                    dp[u][i] += tmp;
                }
            }
        };
        dfs(0, 0);
        LL ans = inf;
        for(int i = 0; i < k; ++ i)
            ans = min(ans, dp[0][i] + pcost[0][i]);
        cout << ans << '\n';
    }else if (m == n){
        vector<int> id(n);
        iota(id.begin(), id.end(), 0);
        int ignore = 0;
        function<int(int)> findfa = [&](int x){
            return x == id[x] ? x : id[x] = findfa(id[x]);
        };
        for(int i = 0; i < m; ++ i){
            int u = edges[i][0], v = edges[i][1];
            int fu = findfa(u), fv = findfa(v);
            if (fu == fv){
                ignore = i;
                break;
            }
            id[fu] = fv;
        }
 
        vector<vector<LL>> dp(n, vector<LL>(k, 0));
        LL ans = inf;
        int fixed = edges[ignore][0], st = edges[ignore][1];
        for(int col = 0; col < k; ++ col){
            for(auto &i : dp)
                fill(i.begin(), i.end(), 0);
            function<void(int, int)> dfs = [&](int u, int fa){
                for(auto e : edge[u]){
                    int v = e[0], id = e[1];
                    if (v == fa || id == ignore)
                        continue;
                    dfs(v, u);
                    for(int i = 0; i < k; ++ i){
                        if (u == fixed && i != col)
                            continue;
                        LL tmp = inf;
                        for(int j = 0; j < k; ++ j){
                            if (v == fixed && j != col)
                                continue;
                            int L = i, R = j;
                            if (u != edges[id][0])
                                swap(L, R);
                            int r = L * k + R;
                            tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
                        }
                        dp[u][i] += tmp;
                    }
                }
            };
            dfs(st, st);
            for(int i = 0; i < k; ++ i){
                int L = i, R = col;
                if (st != edges[ignore][0])
                    swap(L, R);
                int r = L * k + R;
                ans = min(ans, dp[st][i] + pcost[st][i] + ecost[ignore][r]);
            }
 
        }
        cout << ans << '\n';
 
    }else{
 
        vector<int> du(n);
        for(int i = 0; i < m; ++ i){
            int u = edges[i][0], v = edges[i][1];
            ++ du[u];
            ++ du[v];
        }
        int target = 0;
        for(int i = 0; i < n; ++ i){
            if (m - du[i] == n - 2){
                target = i;
                break;
            }
        }
        vector<int> forbid(n, 0);
        for(auto &e : edge[target]){
            int v = e[0];
            forbid[v] = 1;
        }
        int st = 0;
        while(st == target || forbid[st])
            ++ st;
 
        vector<vector<LL>> dp(n, vector<LL>(k, 0));
        LL ans = inf;
        for(int col = 0; col < k; ++ col){
            for(auto &i : dp)
                fill(i.begin(), i.end(), 0);
            function<void(int, int)> dfs = [&](int u, int fa){
                for(auto e : edge[u]){
                    int v = e[0], id = e[1];
                    if (v == fa)
                        continue;
                    if (v != target)
                        dfs(v, u);
                    for(int i = 0; i < k; ++ i){
                        LL tmp = inf;
                        for(int j = 0; j < k; ++ j){
                            if (v == target && j != col)
                                continue;
                            int L = i, R = j;
                            if (u != edges[id][0])
                                swap(L, R);
                            int r = L * k + R;
                            if (v == target){
                                tmp = min(tmp, 1ll * ecost[id][r]);
                            }else{
                                tmp = min(tmp, dp[v][j] + pcost[v][j] + ecost[id][r]);
                            }
                        }
                        dp[u][i] += tmp;
                    }
                }
            };
            dfs(st, st);
            for(int i = 0; i < k; ++ i){
                ans = min(ans, dp[st][i] + pcost[st][i] + pcost[target][col]);
            }
 
        }
        cout << ans << '\n';
 
    }
 
    return 0;
}

 运行结果:

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

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

相关文章

贝叶斯网络:利用变量消除(Variable Elimination)进行推理

贝叶斯网络简介 贝叶斯网络(Bayesian network)也叫贝氏网路、信念网络&#xff08;belief network&#xff09;或是有向无环图&#xff08;DAG&#xff09;模型&#xff0c;是一种概率图模型。它利用DAG的结构&#xff0c;得到一组随机变量{X1,X2,...,Xn}的条件概率分布&#…

Java中的static

目录 static修饰成员变量 静态成员变量特征 static修饰成员方法 【静态方法特性】 static成员变量初始化 就地初始化 静态代码块初始化 注意事项 static修饰成员变量 静态成员变量特征 static修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;静态成员变量最大的…

matplotlib从起点出发(10)_Tutorial_10_Layout

使用受约束的绘图干净整洁地将图形合适排列。 受约束的布局会自动调整子图&#xff0c;以便刻度标签、图例和颜色条等装饰不会重叠&#xff0c;同时仍保留用户请求的逻辑布局。 受约束布局类似于“紧密布局”&#xff0c;但它要更灵活。它处理放置在多个轴上的Axes(放置颜色条…

python 命令行界面的用户交互

背景 说一千&#xff0c;道一万&#xff0c;程序是为用户服务的&#xff0c;所以在程序运行过程&#xff0c;与用户交互以获取用户的信息输入和决策确认&#xff0c;是无法避免的编程需要考虑和解决的需求。 一个简单的demo 如下的程序中&#xff0c;程序需要生成一个新的 i…

图片批量归类:告别混乱,实现高效文件管理

在日常生活中&#xff0c;我们经常需要处理大量的图片文件。这些图片可能来自于不同的设备、不同的目录&#xff0c;甚至不同的存储介质。随着时间的推移&#xff0c;这些图片文件会越来越多&#xff0c;管理起来也会越来越困难。如何高效地整理这些图片文件&#xff0c;告别混…

初步利用Ansible实现批量服务器自动化管理

1.Ansible介绍 Ansible是一款开源的自动化运维工具, 在2012年由Michael DeHaan创建, 现在由Red Hat维护。Ansible是基于Python开发的,采用YAML语言编写自动化脚本playbook, 可以在Linux、Unix等系统上运行, 通过SSH协议管理节点, 无需在被管理节点安装agent。Ansible以其简单、…

MySQL 数据库安全性练习题

数据库安全性 一、实验目的 &#xff08;1&#xff09;熟悉通过MySQL对数据进行安全性控制 二、实验环境 Windows 11 MySQL Navicat 三、实验内容 今有以下两个关系模式&#xff1a; 职工&#xff08;职工号&#xff0c;姓名&#xff0c;年龄&#xff0c;职务&#xff0c;工…

11.3递归建二叉树,二叉树函数规范化输入输出,一些二叉树性质,求叶子结点与树的高度

建树 &#xff0c;递归建树 输入为 建立树 递归 函数参数表为引用或指针 void Creat(BiTree *T){char ch;scanf("%c",&ch);if(ch#){*TNULL;}else{*T(BiTree)malloc(sizeof(BiTNode));(*T)->datach;Creat(&(*T)->nextleft);Creat(&(*T)->nex…

标签识别中的数据泄露:关键分析

一、介绍 在数据驱动的决策时代&#xff0c;收集、处理和分析数据的过程在从医疗保健到金融&#xff0c;从营销到研究的各个领域都发挥着举足轻重的作用。数据分析的基本步骤之一是正确识别数据集中的标签或类别。然而&#xff0c;这项看似简单的任务可能充满挑战&#xff0c;尤…

springboot苍穹外卖实战:八、开发小程序准备工作+入门案例+小程序微信用户登录流程+商品浏览

开发小程序准备工作 官方网址&#xff1a;https://mp.weixin.qq.com/cgi-bin/wx?token&langzh_CN 1、微信小程序注册 注册地址&#xff1a;https://mp.weixin.qq.com/wxopen/waregister?actionstep1 2、 完善小程序信息 登录小程序后台&#xff1a;https://mp.weixin.…

前端框架Vue学习 ——(三)Vue生命周期

生命周期&#xff1a;指一个对象从创建到销毁的整个过程。 生命周期的八个阶段&#xff1a;每触发一个生命周期事件&#xff0c;会自动执行一个生命周期方法&#xff08;钩子&#xff09; mounted&#xff1a;挂载完成&#xff0c;Vue 初始化成功&#xff0c;HTML 页面渲染成功…

Linux学习第33天:Linux INPUT 子系统实验(二):Linux 自带按键驱动程序的使用

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本节笔记主要内容是学会如何使用Linux自带的按键驱动程序。 一、自带按键驱动程序源码简析 配置选项路径如下&#xff1a; -> Device Drivers ->…

内存学习(3):DRAM的基础存储结构(存储层级、读写过程,刷新与暂存)

1 DRAM背景简介 DRAM&#xff0c;全称为 Dynamic Random Access Memory &#xff0c;中文名是“动态随机存取存储器”。所谓“动态”是和“静态”相对应的&#xff0c;芯片世界里还有一种 SRAM 静态随机存取存储器的存在。 笼统地说&#xff0c;DRAM 的结构比 SRAM 更简单&am…

UE5——源码阅读——2

这个是非常大的作用域&#xff0c;当程序离开这个东西&#xff0c;就会把它释放掉&#xff0c;设置了一个作用域把当前线程标记为主线程 插入了一个默认的Main,这个东西其实是标记点&#xff0c;这个标记是在UE内部有个性能分析工具可以看到这个标记点&#xff0c;主要是确定位…

【java学习—十三】处理流之三:标准输入输出流(3)

文章目录 1. 相关概念2. 举例与练习2.1. 举例2.2. 练习 1. 相关概念 System.in 和 System.out 分别代表了系统标准的输入和输出设备&#xff0c;默认输入设备是键盘&#xff0c;输出设备是显示器。     System.in 的类型是 InputStream     System.out 的类型是 PrintS…

SpringMvc从菜鸟到大拿完成蜕变

SpringMvc从菜鸟到大拿完成蜕 介绍 Why springmvc Servlet缺点: servlet中的service:方法一次只能处理一类请求;单拿用户表来说,得需要创建五个Servlet;在url中输入的是urlpattern;默认只访问service方法;如何减少Servlet的个数呢? 增加了一个method参数;其他人有可能会喜欢…

腾讯云CVM S5服务器优惠价格表,买一年送3个月

腾讯云服务器CVM标准型S5有活动&#xff0c;CVM 2核2G S5优惠价280.8元一年自带1M带宽&#xff0c;15个月313.2元、2核4G配置748.2元15个月、4核8G配置1437.24元15个月、8核16G优惠价3048.48元15个月&#xff0c;公网带宽可选1M、3M、5M或10M&#xff0c;腾讯云服务器网txyfwq.…

【算法练习Day39】单词拆分多重背包的介绍

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 单词拆分多重背包总结&…

[BUUCTF NewStar 2023] week5 Crypto/pwn

最后一周几个有难度的题 Crypto last_signin 也是个板子题&#xff0c;不过有些人存的板子没到&#xff0c;所以感觉有难度&#xff0c;毕竟这板子也不是咱自己能写出来的。 给了部分p, p是1024位给了922-101位差两头。 from Crypto.Util.number import * flag b?e 655…

Winform 实现俄罗斯方块游戏(一)

第一步&#xff0c;先用GDI绘制小正方形方块&#xff0c;其它形状的用这个方块合成 如何绘制一个方块&#xff1f;先绘制两个正方形&#xff0c;如下&#xff1a; 然后四周用梯形填充&#xff0c;内部颜色用渐变&#xff0c;这样更有立体感&#xff0c;下篇介绍如何实现。