一道有意思的图论题

news2024/9/29 5:35:11

今天写这道题的过程就一直在摆,主要是写不太出来,之前想到动态规划去了,然后又开始深搜,在出口那块放动态规划
题:
D. Ela and the Wiring Wizard
点我
但是cf让我明白了一个道理,任何一道我写不出来的题代码不会超过50行,嘤(的确,太长的也不太好调试,这样的题显然不是模拟,要推出一些结论,然后往上整
这个题的大意是 u i , v i , t i u_{i},v_{i},t_{i} ui,vi,ti通过 v i v_{i} vi相连,那么可以花费 u i , v i u_{i},v_{i} ui,vi之间的权重把这两条边断开,然后把 u i , t i u_{i},t_{i} ui,ti连在一起,这样的话走 u i , t i u_{i},t_{i} ui,ti就可以使用 u i , v i u_{i},v_{i} ui,vi之间的权重了。这样的操作可以进行任意多次,求最后从 1 → n 1\rightarrow n 1n的最小花费是多少,把消边的时间也要算上。
现在看来,我的做法的确很沙雕。我的错误在于,我是深搜出一条从 1 1 1 n n n的路径,然后把这条路径动规,但是这里面有一个问题就是,如果一开始的一条路径不能从 1 1 1走到 n n n,这条路径也有可能通过操作最短。
你看这个图,他的答案是 154 154 154,为啥,我当时还在想是 43 , 54 43,54 4354怎么组合,因为我算的一直都是 162 162 162,后来我才明白,他一直在用 22 22 22那条边来回倒。
你可以
在这里插入图片描述
比如这个图首先 2 2 2通过 5 5 5连到 4 4 4上,花费 2 2 2 22 22 22,然后 4 4 4通过 2 2 2连到 4 4 4上,花费 1 1 1 22 22 22,然后, 4 4 4通过 4 4 4连到 1 1 1上花费 2 2 2 22 22 22,然后 1 1 1通过 4 4 4连到 8 8 8上,花费 1 1 1 22 22 22,最后从 1 1 1走到 8 8 8花费 1 1 1 22 22 22
这种是间接连接, u u u v v v之间的连边变化情况:走 v v v i i i个路径让 u u u连到 i i i上,然后 v v v i i i相连之后,让 i i i i i i形成自环,然后让 i i i 1 1 1 n n n连接,花费 i i i 1 1 1 i i i n n n的路径。最后再走一条边(运行时)
直接连接: u u u先连到 1 1 1,然后 1 1 1再连到 n n n u u u连到 1 1 1走的时 v v v到1的路径然后 1 1 1连到 n n n走的是 u u u n n n的路径,画个图就知道了
所以方程是:

// direct connect
		ans = min(ans, 1LL * w * (f[0][u] + f[v][n-1] + 1));
		ans = min(ans, 1LL * w * (f[0][v] + f[u][n-1] + 1));
		
		// indirect connect
		for (int k = 0; k < n; ++k) {
			ans = min(ans, 1LL * w * (f[v][k] + 1 + f[k][0] + f[k][n-1] + 1));
			ans = min(ans, 1LL * w * (f[u][k] + 1 + f[k][0] + f[k][n-1] + 1));
		}
 

以上思路参考文章:
参考文章
(AC代码):

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define min(a,b) ((a<b)?a:b)
typedef long long ll;
const int length = 505;
vector<pair<int, pair<int, int>>> edge;
int f[length][length];
int main(void)
{
	int t;
	scanf_s("%d", &t);
	for (int i = 0; i < t; i++)
	{
		edge.clear();
		int n, m;
		scanf_s("%d%d", &n, &m);
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (i == j)f[i][j] = 0;
				else f[i][j] = INT_MAX>>1;
			}
		}
		for (int i = 0; i < m; i++)
		{
			int a, b, c;
			scanf_s("%d%d%d", &a, &b, &c);
			edge.push_back({ a,{b,c} });
			f[a][b] = 1;
			f[b][a] = 1;
		}
		for (int k = 1; k <= n; k++)
		{
			for (int i = 1; i <= n; i++)
			{
				for (int j = 1; j <= n; j++)
				{
					f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
				}
			}
		}
		ll ans = LLONG_MAX;
		for (int i = 0; i < m; i++)
		{
			int u = edge[i].first;
			int v = edge[i].second.first;
			int w = edge[i].second.second;
			//直接
			ans = min(ans, (ll)w*(f[u][1] + f[v][n] + 1));
			ans = min(ans, (ll)w*(f[v][1] + f[u][n] + 1));

			//间接
			for (int i = 1; i <= n; i++)
			{
				ans = min(ans, (ll)w*(f[u][i] + 1 + f[i][1] + f[i][n] + 1));
				ans = min(ans, (ll)w*(f[v][i] + 1 + f[i][1] + f[i][n] + 1));
			}
		}
		printf("%lld\n", ans);
	}
}

我写的沙雕代码:

#include<iostream>
#include<cstdio>
#include<vector>
#define min(a,b) ((a<b)?a:b)
using namespace std;
typedef long long ll;
class s
{
public:
	ll weight;
	ll cost;
	s()
	{

	}
	s(int yh)
	{
		weight = yh;
		cost = 0;
	}
	ll operator +( s a)
	{
		return 2*weight + cost + a.cost;
	}
	 
};

const int length = 505;
struct s linjie[length][length];
bool flag[length][length];
ll dp[length][length];
vector<int> s1;
vector<vector<int>> edge(length);
int vis[length];
int n;
ll res = LLONG_MAX;
void dfs(int cur, int fa)
{
	if (cur == n)
	{
		int yh1 = s1.size();
		for (int length = 2; length <yh1; length++)
		{
			for (int i = 0; i <yh1 - length; i++)
			{
				int j = i + length;
				int u = s1[i];
				int v = s1[j];
				ll yh = min(dp[u][v],linjie[u][v].weight+linjie[u][v].cost);//这个yh草率了
				for (int k = 1; k <= n; k++)
				{
					//if (!(flag[u][k] && flag[k][v]))continue;
					if ((linjie[u][k] + linjie[k][v] )< yh&&linjie[k][v].weight!=INT_MAX>>1)
					{
						linjie[u][v].weight = linjie[v][u].weight=linjie[u][k].weight;
						linjie[u][v].cost = linjie[v][u].cost=linjie[u][k].cost + linjie[k][v].cost+linjie[u][k].weight;
						
					}
					if ((linjie[v][k] + linjie[k][u]) < yh&&linjie[k][u].weight!=INT_MAX>>1)
					{
						linjie[u][v].weight = linjie[v][u].weight = linjie[v][k].weight;
						linjie[u][v].cost = linjie[v][u].cost = linjie[v][k].cost + linjie[k][u].cost+linjie[v][k].weight;
					}
				}
			}
		}
		res = min(res, linjie[1][n].weight+linjie[1][n].cost);
		return;
	}
	for (int i=1;i<=n;i++)
	{
		int v = i;
		if (!vis[v] && v != fa&&flag[cur][v])
		{
			s1.push_back(v);
			vis[v] = 1;
			dfs(v, cur);
			s1.pop_back();
			vis[v] = 0;
		}
	}
}
int main(void)
{
	int t;
	scanf_s("%d", &t);
	for (int i = 0; i < t; i++)
	{
		int m;
		scanf_s("%d%d", &n, &m);
		res = LLONG_MAX;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				linjie[i][j].weight = INT_MAX>>1;
				linjie[i][j].cost = 0;
				dp[i][j] = INT_MAX >> 1;
			}
		}
		for (int i = 0; i < m; i++)
		{
			int a, b, c;
			scanf_s("%d%d%d", &a, &b, &c);
			linjie[a][b].weight = min(linjie[a][b].weight,c);
			linjie[b][a].weight = min(linjie[b][a].weight,c);
			flag[a][b] = 1;
			flag[b][a] = 1;
			dp[a][b] = min(dp[a][b],c);
			dp[b][a] = min(dp[b][a],c);
		}
		for (int k = 1; k <= n; k++)
		{
			for (int i = 1; i <= n; i++)
			{
				for (int j = 1; j <= n; j++)
				{
					dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
				}
			}
		}
		vis[1] = 1;
		s1.push_back(1);
		for(int i=n-1;i>=1;i--)
	     	dfs(i, -1);
		printf("%lld\n", min(dp[1][n],res));
	}
}

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

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

相关文章

点菜方案数

题目描述 不过uim的口袋里只剩 M元(M < 10000)&#xff0c;来到了一家低端餐馆前。 餐馆虽低端&#xff0c;但是菜品种类不少&#xff0c;有 N 种(N < 100)&#xff0c;第i种卖元(ai < 1000)。由于是很低端的餐馆所以每种菜只有一份。 uim奉行“不把钱吃光不罢休”&a…

作用域与作用域链

javascript拥有一套设计良好的规则来存储变量&#xff0c;并且之后可以方便的找到这些变量&#xff0c;这套规则叫做作用域。 内部原理 内部原理分成编译、执行、查询、嵌套和异常五部分。今天来简单说一下查询。 var a2;这行代码中&#xff0c;在引擎执行的第一步操作中&am…

【C++ Primer】阅读笔记(3):decltype

目录 简介decltype基础decltype需要注意的地方1.decltype处理顶层const、引用与auto不同2.如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。3.如果表达式的内容是解引用操作,则decltype会得到引用类型。4.对于decltype所用的表达式来说,如果变量…

Spring AOP统一功能处理

⭐️前言⭐️ 这篇文章主要介绍AOP&#xff08;Aspect Oriented Programming&#xff09;——面向切面编程的思想&#xff0c;它是对某一类事情的集中处理&#xff0c;也是对OOP&#xff08;Object Oriented Programming&#xff09;面向对象编程的补充和完善。 &#x1f349;…

【编程语言选择】我们学C++将来能做什么?

首先贴上C嘎嘎祖师爷的镇楼帅照&#x1f606; 凝视目录 什么是C C的使用广泛度 C的具体工作领域有什么 什么是C 简单说 C是基于C语言而产生的&#xff0c;它既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的基于对象的程序设计&#xff0c;还可…

【区块链 | 前端】前端开发人员入门区块链的最佳实践

前端开发人员入门区块链的最佳实践 一. 建立信仰 从技术入门一个行业通常是漫无目的&#xff0c;个人认为正确的入行区块链的方式是去了解他的背景&#xff0c;是去建立自己信仰的&#xff0c;尤其身处一个刚起步就被扼杀的行业&#xff0c;我们每个人都是领头人&#xff0c;我…

06栈和队列

开始系统学习算法啦&#xff01;为后面力扣和蓝桥杯的刷题做准备&#xff01;这个专栏将记录自己学习算法是的笔记&#xff0c;包括概念&#xff0c;算法运行过程&#xff0c;以及代码实现&#xff0c;希望能给大家带来帮助&#xff0c;感兴趣的小伙伴欢迎评论区留言或者私信博…

[NOIP 2003] 栈(三种方法:DP、数论、搜索)

[NOIP2003 普及组] 栈 题目背景 栈是计算机中经典的数据结构&#xff0c;简单的说&#xff0c;栈就是限制在一端进行插入删除操作的线性表。 栈有两种最重要的操作&#xff0c;即 pop&#xff08;从栈顶弹出一个元素&#xff09;和 push&#xff08;将一个元素进栈&#xff…

5 个必须尝试的无代码应用

无代码软件让任何人无需了解编程语言即可构建产品、网站和应用程序。Editor XWix 发布了Editor X&#xff0c;这是一款无需编写任何 CSS &#xff08;层叠样式表&#xff09;或 HTML&#xff08;超文本标记语言&#xff09;代码的新型拖放式网站构建器&#xff0c;为设计师和机…

如何把可观测需求落地为业务大盘?

2022 年 9 月 28 日&#xff0c;阿里云用户组&#xff08;AUG&#xff09;第 11 期活动在深圳举办。活动现场&#xff0c;阿里云技术专家李加贝向参会企业代表分享了如何把可观测需求落地为业务大盘的议题。本文根据现场分享内容整理而成。 为什么需要 Grafana&#xff1f; 演…

智能合约Smart Contract技术详解

文章目录合约编写基本介绍构造方法ipfsmint提现白名单合约前端部署验证合约代码前端和合约交互准备工作获取已经mint了的数量mint合约编写 建议读者先了解下solidity&#xff0c;这里推荐CryptoZombies&#xff0c;还是比较详细的。 ok当你大概知道自己在做什么之后&#xff0…

【概率论】期末复习笔记:假设检验

假设检验目录一、假设检验的基本概念1. 假设检验的基本原理2. 两类错误3. 假设检验的一般步骤4. ppp值二、正态总体参数的假设检验σ2已知&#xff0c;检验μ与μ0的关系\color{dodgerblue}\sigma^2\text{已知&#xff0c;检验}\mu\text{与}\mu_0\text{的关系}σ2已知&#xff…

上海华清远见

解析设备树节点信息实例1获取属性数值实例2获取u32类型的值将获取到的u32类型的值存放在array数组中

什么是许可式邮件营销?

邮件是很多企业日常中用到的信息传播工具&#xff0c;并且它还具备了成本低、长期性等优点&#xff0c;所以很多企业选择使用邮件作为载体进行营销推广。而在进行邮件营销的时候&#xff0c;不同的方式和技巧也会影响到最终的营销效果。为了达到较好的营销效果&#xff0c;很多…

Seata应用

下载seata-server 下载地址&#xff1a;Tags seata/seata GitHub 配置Seata-server 第一步&#xff1a;配置seata-server数据源 E:\seata-server-1.4.2\seata\seata-server-1.4.2\conf\file.conf 第二步&#xff1a;创建seata数据库 create database seata 第三步&#xf…

单元测试-SpringBoot Test和Mock

单元测试-SpringBoot Test和Mock “单元测试” “junit&#xff0c;mock&#xff0c;桩” 1. 什么是单元测试 定义&#xff1a;是指对软件中的最小可测试单元进行检查和验证。 Java里单元指一个方法。单元测试是在软件开发过程中要进行的最低级别的测试活动&#xff0c;软件的…

玻纤效应对skew的影响(三)

玻纤效应对skew的影响&#xff08;一&#xff09;玻纤效应对skew的影响&#xff08;二&#xff09;对内skew对32Gbps NRZ和64Gbps PAM-4的影响这一篇中&#xff0c;玻纤效应造成的对内skew将会加入到32Gbps NRZ和64Gbps PAM-4 SerDes全链路分析中。PCIe 5.0代表32Gbps NRZ&…

C++GUI之wxWidgets(11)-编写应用涉及的类和方法(6)-事件处理(5)

目录自定义事件wxPostEvent()wxQueueEvent()PopEventHandler()Bind()GetEventUserData()Connect()Unbind()定义自己的事件类事件处理程序与虚拟方法自定义事件 wxPostEvent() void wxPostEvent ( wxEvtHandler * dest,const wxEvent & event ) 在GUI应用程序中&am…

云开发项目中如何管理用户和管理授权?

管理用户 在项目中添加用户后&#xff0c;才能为用户授予对应的资产管理权限。支持修改已创建用户的密码和删除用户。 本文中的 用户 是指在云项目下创建的 B 端子账号&#xff0c;可以和资产授权配合使用&#xff0c;管理 B 端设备和资产。这些 B 端用户账号可以在 智慧行业…

IOS开发基础 · SwiftUI · CS193p Lecture1-2

IOS开发Lecture 1TextRoundedRectangleZstackLecture 2HStackstruct整合组件ContentViewstruct 中创建变量var&letSwiftUI刷新重建点击效果ArrayForeachButtonSpacervar整合小组件SF-symbol上下界限制简化ButtonLecture 1 Text import SwiftUIstruct ContentView: View {…