首页 > 其他分享 >暑假集训D5 2023.7.28 补题

暑假集训D5 2023.7.28 补题

时间:2023-07-28 18:34:22浏览次数:37  
标签:cnt dist int 28 vis 2023.7 补题 true dis

首先来回顾一下 \(dijkstra\) 和 \(SPFA\) 里面 \(vis\) 数组的作用和区别,以及不用 \(vis\) 数组的影响.(今天发现之前写堆优化的 \(Dijkstra\) 都不加 \(vis\) 数组...)

  • \(Dijkstra\) 算法中,每次取出距离源点最近的一个点来更新与他相连的其他点,置 \(vis\) 数组为 \(true\) . 如果在更新之前发现已经 \(vis\) 过了,直接 \(continue\) ,原因是这个点早就是距离源点最近的点了,如果没有负权边,那么不可能再有其他点来更新这个点的 \(dist\) ,并且已经用这个点更新过与他相连的点.因此再取出这个点不会再更新到其他点的信息了,额外浪费了时间.

  • \(SPFA\) 算法中, \(vis\) 数组主要是标记这个点是否已经在队列里.那么就很好理解什么时候置 \(vis\) 为 \(false\) \(or\) \(true\) ,什么时候置为 \(true\) .其主要作用是防止一个元素重新入队.

其实可以去掉vis数组,但是这样会导致某一时刻队列中包含多个同一元素,极大地降低了算法的效率。因为同一时刻队列中有多个同一元素和只有一个该元素的效果是一样的。

B.[USACO06DEC] Wormholes G

容易看出本题求负环就可以了.先给出 OIWIKI 上的 SPFA 求负环的模板代码

struct edge {
  int v, w;
};

vector<edge> e[maxn];
int dis[maxn], cnt[maxn], vis[maxn];
queue<int> q;

bool spfa(int n, int s) {
  memset(dis, 63, sizeof(dis));
  dis[s] = 0, vis[s] = 1;
  q.push(s);
  while (!q.empty()) {
    int u = q.front();
    q.pop(), vis[u] = 0;
    for (auto ed : e[u]) {
      int v = ed.v, w = ed.w;
      if (dis[v] > dis[u] + w) {
        dis[v] = dis[u] + w;
        cnt[v] = cnt[u] + 1;  // 记录最短路经过的边数
        if (cnt[v] >= n) return false;
        // 在不经过负环的情况下,最短路至多经过 n - 1 条边
        // 因此如果经过了多于 n 条边,一定说明经过了负环
        if (!vis[v]) q.push(v), vis[v] = 1;
      }
    }
  }
  return true;
}

在应用 \(SPFA\) 求负环时,一定要注意看一下图是不是连通的,如果不是连通的,一定要把所有点都用一遍 \(SPFA\) .
可以用下面两种方法:

for(int i = 1;i<=n;i++)
{
	if(!vis[i])
	{
		spfa(n,i);
	}
}

第二种方法是预先把所有点都加进队列中.

bool spfa()
{
	queue<int> q;
	memset(vis, 0, sizeof vis);
	memset(cnt, 0, sizeof cnt);
	memset(dist, 0x3f, sizeof dist);
	dist[1] = 0;
	//把所有点预先加进去.这样就不用担心不连通了.
	for(int i =1;i<=n;i++)
	{
		q.push(i);
		vis[i] =1;
	}
	while (q.size())
	{
		int u = q.front();
		q.pop(), vis[u] = 0;
		for (int  i = h[u]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (dist[j] > dist[u] + c[i])
			{
				dist[j] = dist[u] + c[i];
				cnt[j] = cnt[u] + 1;
				//cout<<u<<" "<<j<<dist[j]<<endl;
				//system("pause");
				if (cnt[j] > n)return false;
				if (!vis[j]) q.push(j), vis[j] = 1;
			}
		}
	}
	return true;
}

标签:cnt,dist,int,28,vis,2023.7,补题,true,dis
From: https://www.cnblogs.com/oijueshi/p/17588463.html

相关文章

  • 【2023-07-28】渴望亲密关系
    20:00人没有苦闷,没有矛盾,就不会进步。有矛盾才会逼你解决矛盾,解决一次矛盾即往前迈进一步。到晚年矛盾减少,即是生命将要告终的表现。没有矛盾的一片恬静只是一个崇高的理想,真正实现的话并不是一个好现象。                      ......
  • 国标GB28181视频平台LntonGBS(源码版)国标视频平台大并发下SIP消息出现重复SN号的问题解
    随着国家倡导平安城市、智慧城市的建设,安防视频监控作为智慧城市安防建设的重要环节,也越来越受到重视。LntonGBS是基于公安部推出的安防主流协议(国标GB28181协议)的视频接入、处理及分发平台,具有视频直播监控、云端录像、云存储、检索回放、智能告警、语音对讲、平台级联等功能。我......
  • 【2023.07.28】三年计划
    =主线任务今年的主线是考上研究生,并让学校所有人都认识我攒钱买辆车(大概率小米)明年的主线是软考高项,业余时间去考电工和思科支线任务增肥上60kg,让自己身体更好,目前只有53还是太瘦了和妹妹拼完一整个柜子的积木(目前四层已经塞满两层)谈恋爱,找女朋友入校后打算......
  • 2023-07-28 后端接口返回的数据与postman返回的数据不一致 ==》前端不兼容数据库字段
    前言:在传参一致,接口一致的情况下,微信开发者工具调的接口和postman返回的数据的id不一致。具体为:微信开发者工具端调接口拿到的id为22位的数据:1884661033952220199看起来平平无奇对吧,而postman返回的id则为:1884661033952220200是的,接口一样,传参一样,返回的其它数据也一样,唯独这......
  • 2023.7.27 周四:static
    1publicclassStudent{2privateintage;//非静态变量3privatestaticintscore;//静态变量4publicvoidrun(){56}7publicstaticvoidgo(){89}1011publicstaticvoidmain(String[]args){12Stud......
  • 开源视频监控管理平台国标GB28181视频EasyCVR电子地图功能展示优化
    视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。视频监控综合管理平台EasyCVR可提供的视频能力包括:视频监控直播、云端录像、云存储、录像检索与回......
  • 2023.7.26
    吃完鸡蛋面就告别了早晨,早上看了看视频就过去了,中午煮好饭看了会儿书有些困,吃了饭便休息了一会儿,下午学习新的语言,有些难,又学起了java,现在已经学得很舒服了,只要不涉及很难的都能看懂掌握,晚上打了会儿游戏也休息了。......
  • 2023.7.26
    今天上午没有出去跑步,在家里跳了帕姐的训练,结果没到三分之一就累的要死(太脆了)中午又被热的头昏不过下午醒来以后拿出来了我的cos服又试了一下我的蝴蝶忍技术比以前好多了下次继续努力!......
  • 2023.7.25 将数组和减半的最少操作次数
    贪心,显然每次都削减最大数的一半,可以更快的接近至少削减一半的目标。可以证明,削减任何不是最大数的一半,都不会优于削减最大数的一半,因为题目要求不是正好减少一半,而是至少减少一半。所以可以开一个大根堆存储所有的数,每次取出堆顶的数进行减半,然后将减半后的数插入堆中,并且更新......
  • 算法学习笔记(28): 筛法
    筛法线性筛杜教筛放在偏序关系\((\Z,|)\)中卷积……如何快速的求\(S(n)=\sum_{i=1}^nf(i)\)。如果能够找到一个函数\(g\):\[\begin{aligned}\sum_{i=1}^n(f*g)(i)&=\sum_{i=1}^n\sum_{d|i}f(\fracid)g(d)\\&=\sum_{d=1}^{n}g(d)\sum_{i......