johnson最短路模板(未完成,自用)

johnson最短路

https://www.starrycoding.com/problem/100

关键就在于,解决dijkstra不能处理负权值的问题,先用spfa或者bellman-ford得到所有点到虚点的最短距离,可以称之为势能。然后通过势能对所有边进行处理,处理过后保证了所有边都是正的,再对每个点跑dijkstra就能实现全源带负权的最短路。跑完后再通过势能还原回来。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 3e3 + 5;
const ll inf = 4e18 + 5;

int n, m;

struct Edge
{
	ll y, w;
	bool const operator < (const Edge& a)const
	{
		return w == a.w ? y < a.y : w > a.w;//注意此处大于号
	}
};

vector<Edge>g[M];
ll d[M][M];//记录全源最短路
ll h[M];//虚点的单源最短路(势能)
bitset<M>vis;
queue<int>q;
int cnt[M];

int spfa(int st)
{
	q.push(0);
	vis[0] = 1;
	while(q.size())
	{
		int x = q.front();
		q.pop();
		vis[x] = 0;

		for (auto& [y, w] : g[x])
		{
			if (h[y] > h[x] + w)
			{
				h[y] = h[x] + w;
				cnt[y]++;
				if (cnt[y] >= n)
					return 0;
				if (!vis[y])
				{
					vis[y] = 1;
					q.push(y);
				}
			}
		}
	}

	return 1;
}

void dijkstra(int st, ll d[])
{
	for (int i = 1; i <= n; i++)
		d[i] = inf;

	priority_queue<Edge>pq;
	vis.reset();
	
	pq.push({ st,d[st] = 0 });
	while (pq.size())
	{
		int x = pq.top().y; pq.pop();
		if (vis[x])continue;
		vis[x] = true;
		for (auto &[y, w] : g[x])
		{
			if (d[y] > d[x] + w)
			{
				d[y] = d[x] + w;
				pq.push({ y, d[y] });
			}
		}
	}
	//还原回来
	for (int i = 1; i <= n; ++i)d[i] = d[i] - h[st] + h[i];
}

void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		ll x, y, z;
		cin >> x >> y >> z;
		g[x].push_back({ y,z });
	}
	
	//创建虚点0,默认0到所有点的距离是0
	for (int i = 1; i <= n; i++)
	{
		g[0].push_back({ i,0 });
		h[i] = inf;
	}
	
	//spfa得出虚点最短路
	if (!spfa(0))//如果存在负环直接跳出
	{
		cout << "starrycoding" << '\n';
		return;
	}

	//将所有边进行改动
	for (int i = 1; i <= n; i++)
	{
		for (auto& [y, w] : g[i])//一定要加引用!!
			w = w + h[i] - h[y];
	}

	//每个点跑一遍 dijkstra
	for (int i = 1; i <= n; i++)
		dijkstra(i, d[i]);
		
	int q;
	cin >> q;
	while (q--)
	{
		int x, y;
		cin >> x >> y;
		//有的点可能被更新过,所以此处用inf/2
		if (d[x][y] >= inf / 2)cout << "noway" << '\n';
		else
			cout << d[x][y] << '\n';
	}
}

int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	solve();
	return 0;
}

其他博主比较好的文章
https://blog.youkuaiyun.com/hzf0701/article/details/107697261

### STM32串口重定向 `fputc` 出现乱码的原因分析 在STM32开发过程中,当通过 `fputc` 实现串口重定向时,如果出现乱码现象,通常可能是由以下几个原因引起的: #### 1. **波特率设置不匹配** 波特率是通信双方约定的数据传输速率。如果发送端和接收端的波特率不同步,则会导致数据解析错误从而引发乱码问题。需确认STM32中的UART配置与终端工具(如SecureCRT、Putty等)所使用的波特率一致[^1]。 ```c // UART初始化函数中确保波特率正确配置 huart3.Init.BaudRate = 115200; HAL_UART_Init(&huart3); ``` --- #### 2. **Keil编译器未正确开启标准库支持** 为了使 `printf` 和其他标准输入/输出功能正常工作,在Keil项目中需要确保已包含 `<stdio.h>` 并定义了 `_REDIRECT_STDOUT` 宏或者手动实现 `fputc` 的重写逻辑。如果没有正确配置这些选项,可能会导致字符无法被正确处理而产生乱码。 ```c #include "stdio.h" int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF); return ch; } ``` --- #### 3. **中断优先级冲突** 某些情况下,高优先级的中断可能干扰到UART外设的工作流程,特别是对于时间敏感的操作而言。这可能导致部分字节丢失或延迟过大进而造成显示异常。因此建议调整相关外围设备的抢占优先级以及子优先级来避免此类情况发生[^2]。 ```c void MX_NVIC_Configuration(void){ NVIC_SetPriority(USART1_IRQn, 1); // 设置较低的抢占优先级 NVIC_EnableIRQ(USART1_IRQn); } ``` --- #### 4. **缓冲区溢出或其他硬件资源不足** 长时间连续打印大量信息至串口中断模式下运行时容易遇到内存分配失败等问题;另外还需注意电源电压稳定性等因素也可能间接影响通讯质量[^3]。 --- ### 综合解决方案 以下是综合考虑上述各点后的改进措施: - 确认并统一收发两端之间的波特率参数; - 在工程文件里加入必要的头文件声明,并按照实际需求编写合适的 `fputc` 方法体; - 调整好各个模块间的中断级别关系以防互相打扰; - 如果条件允许的话还可以尝试优化现有程序结构减少不必要的开销提高效率。 最终版代码如下所示: ```c #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ PUTCHAR_PROTOTYPE{ HAL_StatusTypeDef status; do{ status=HAL_UART_Transmit(&huartX,(uint8_t*)&ch,1,HAL_MAX_DELAY); }while(status!=HAL_OK); return ch; } ``` > 注:这里的 huartX 应替换为您具体使用的串口号变量名比如 huart1 或者 huart2 等。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值