经过12天的滚粗,终于迎来了暑期培训的结尾啦QAQ

结业考才考了90分,真是对不起孙爷(孙爷请收下我的膝盖)

orz小粉兔怒D rank 1 获得小粉兔一只QAQ

由于这次12天的培训题目又比较多,算法较难,所以只能等到课程结束之后再来补坑了。

现在开始补坑(BEGIN大工程!!)

day1主要知识:最短路+two-sat

首先是最短路:

对于最短路目前我们大部分人用的就是两种算法:

一、dijkstra算法:

dij算法基于的思想就是每次从所有已拓展的节点相连的未拓展的节点取出一个dis值最小的节点加入集合,直到找到所有点的最短路

这种做法唯一的优点就是跑的比spfa快,但是这种算法不能处理负权边。而且也只是处理单源最短路问题

对于找到dis最小值的点有两种方法,第一种就是n^2暴力枚举点,但是这样太慢,所以通常我们把点放入优先队列中或者是堆中优化复杂度

然后我们贴个图来讲解一下具体做法:

一开始的时候没有一个点在集合中:

接下来一号节点入队

我们发现4号节点离1号节点最近,4号节点入队。

接下来我们发现3号节点离1号节点和4号节点最近,3号节点入队

最后二号节点入队

至此,最短路结束。

下面附上例题:

给定N个节点,M条无向边的图,求1号节点到N号节点次短路的长度

备注:次短路是长度大于最短路中最短的路径

——————————————我是分割线——————————————

这道题目显然是单源最短路问题,只不过我们我们找到一个点看能不能更新最短路,如果能就更新,否则再和次短路进行比较。注意这题最短路和次短路不能相同,所以如果一个点的dis值与最短路的值相同要跳过才可以。

下面附上代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define MN 200005
#define M 5005
using namespace std;
int head[M],d1[M],d2[M],n,m,num;
struct e{int to,next,w;
}g[MN];
void ins(int u,int v,int val){g[++num].next=head[u];head[u]=num;g[num].to=v;g[num].w=val;}
void insw(int u,int v,int w){ins(u,v,w);ins(v,u,w);}
void swap(int &a,int &b){a^=b;b^=a;a^=b;}
struct edge{int to,value;edge(int to,int value):to(to),value(value) {}friend bool operator <(edge a,edge b){return a.value>b.value;}
};
priority_queue<edge>q;
void dij(){d1[1]=0;q.push(edge(1,0));while(!q.empty()){edge tmp=q.top();q.pop();if(tmp.value>d2[tmp.to])continue;for(int i=head[tmp.to];i;i=g[i].next){int dd=tmp.value+g[i].w;if(dd==d1[g[i].to])continue;if(dd<d1[g[i].to]){swap(dd,d1[g[i].to]);q.push(edge(g[i].to,d1[g[i].to]));}if(dd<d2[g[i].to]){swap(dd,d2[g[i].to]);q.push(edge(g[i].to,d2[g[i].to]));}}}
}
int main(){scanf("%d%d",&n,&m);memset(d1,0x3f,sizeof(d1));memset(d2,0x3f,sizeof(d2));int x,y,val;for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&val),insw(x,y,val);dij(),printf("%d\n",d2[n]);return 0;
}

二、spfa

spfa的原理与dij有点相像,不过它处理的是多元最短路问题,可以有多个起点,它的基础算法就是松弛操作,只要目前在队中的节点有一条边能使到达其他点的dis值更小,就更新dis值,并且让被更新的节点入队,由于一个点最多入队n次,所以最坏复杂度是O(nm),不过有一些优化可以让这个算法变得更快,这个我们下面讲。

还是刚才那张图

首先1号节点入队(假设只有一个源)

然后我们发现与一号节点相连的点有二号和四号节点。更新dis[2]=50,dis[4]=10,2,4号节点入队。1号节点出对。

然后我们看到了三号节点没有进过队,它的dis值是inf于是3号节点入队,2号节点出队

我们发现4号节点能更新2号节点和3号节点,更新完后4号节点出队

最后我们发现3号节点能够更新2号节点,更新完3号节点出队,最短路结束。

在附上代码之前讲2个优化。

1、SLF优化

因为我们看到上图进行了多次松弛操作,所以复杂度较高。

不过如果我们调换一下入队顺序,比如原来的入队顺序是2 3 4节点

如果我们改成4 3 2节点,我们就会发现没有松弛操作了。一次就得出了正解。

这就是SLF优化。如果当前找到的v(边的终点)节点的dis值比队头元素的dis值更小,那么我们就把这个点放在队头。这样能优化30%左右,并且在本图中效果最为明显。

2、循环队列优化

再讲一个不是优化的优化,就是循环队列。因为在一个队列中最多只能同时存在n(n为点的总数)个元素,所以我们可以将队列循环使用,节省空间。

下面直接附上代码

void spfa(){memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++)dis[i]=inf;dis[T]=0;vis[T]=1;int h=0,t=1;que[1]=T;while(h!=t){int tmp=que[(++h)%=MN];for(int i=head[tmp];i;i=g[i].next)if(g[i^1].w&&dis[g[i].to]-dis[tmp]+g[i].c>eps){dis[g[i].to]=dis[tmp]-g[i].c;if(!vis[g[i].to]){vis[g[i].to]=1;if(dis[g[i].to]<dis[que[(h+1)%MN]])que[h]=g[i].to,h=(h-1+MN)%MN;else que[(++t)%=MN]=g[i].to;}}vis[tmp]=0;}
}

接下来我们讲讲第二个大块two-set

two-sat问题就是这样:对于一个事件你只有两种选择,选,或者不选。

而且对于两个事件间还有一些约束条件,如A、B中至少要选一个。

而two-sat算法就是将这些限制条件转换为不同状态之间的边,然后通过染色来判断满足条件的情况是否存在的。

two-sat最重要的方法就是将一个点拆成2个,一个是选,一个是不选。

举个例子:

假如A、B之间我至少要选一个

那么反之,如果我A没选,那么B一定选

如果我B没选,A我一定选

那么我只要在非A与B,非B与A之间连一条单向边就好了。(非表示不选)

其他的条件同理

下面直接附上例题代码(由于是英文大家就自己理解啦。。我偷懒一下下QAQ)

#include<cstdio>
#include<cstring>
#define MN 100005
using namespace std;
int n,m,tot,x,y,num,top;
int age[MN],vis[MN*2],stack[MN],head[MN*2];
struct edge{int to,next;
}g[MN*8];
void ins(int u,int v){g[++num].next=head[u];head[u]=num;g[num].to=v;}
bool kind(int now){return age[now]*n<tot;}
bool dfs(int u){if(vis[u^1])return false;if(vis[u])return true;vis[u]=true;stack[top++]=u;for(int i=head[u];i;i=g[i].next){if(!dfs(g[i].to))return false;}return true;
}
bool t_sat(){memset(vis,0,sizeof(vis));for(int i=0;i<2*n;i+=2){if(vis[i]||vis[i^1])continue;top=0;if(!dfs(i)){while(top)vis[stack[--top]]=0;if(!dfs(i^1))return false;}}return true;
}
int main(){while(scanf("%d%d",&n,&m)!=EOF){if(n==0&&m==0)break;memset(g,0,sizeof(g));memset(head,0,sizeof(head));memset(stack,0,sizeof(stack));num=tot=0;for(int i=0;i<n;i++)scanf("%d",&age[i]),tot+=age[i];for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);x--,y--;if(kind(x)==kind(y)){ins(x<<1,y<<1|1);ins(y<<1,x<<1|1);}ins(x<<1|1,y<<1);ins(y<<1|1,x<<1);}if(t_sat()){for(int i=0;i<2*n;i+=2){if(!vis[i]){printf("C\n");continue;}else if(kind(i/2))printf("B\n");else printf("A\n");}}else printf("No solution.\n");}
}

转载于:https://www.cnblogs.com/ghostfly233/p/7159631.html

培训补坑(day1:最短路two-sat)相关推荐

  1. python抓取数据时失败_爬取数据缺失的补坑,Python数据爬取的坑坑洼洼如何铲平...

    渣渣业余选手讲解,关于爬取数据缺失的补坑,一点点关于Python数据爬取的坑坑洼洼如何铲平,个人的一些心得体会,还有结合实例的数据缺失的补全,几点参考,仅供观赏,如有雷同,那肯定是我抄袭的! 在使用P ...

  2. C++工作笔记-对结构体中位域的补坑说明

    以前关于位域的连接: https://blog.csdn.net/qq78442761/article/details/80102666 对这篇博文进行补坑说明: 如下: structbs { int ...

  3. Qt工作笔记-ListWidget拖动(拖拽)到QGraphicsScene【补坑】【Qt视图框架补坑】

    关于以前的这篇博文,进行补坑 https://blog.csdn.net/qq78442761/article/details/80957186 坑的位置在这,采用上面这篇博文的配法,无法得到图元在场 ...

  4. python爬虫,g-mark网站图片数据爬取及补坑

    应用python对g-mark网站图片数据爬取,同时但对于数据抓取失败的图片进行补坑(重新爬取操作),由于是日本网站,没有梯子访问的话,特别容易访问超时,比较合适的补坑操作是直接将数据采集到数据库,而 ...

  5. AI 培训之坑,了解一下?

    今天阅读微信公众号的文章,又刷到了一篇AI程序员平均年薪多少多少,Python前景多好多好的文章,我立刻猜到,这肯定又是某家培训给自己的AI课程打的广告. 如今各种公众号类似的文章实在太多了,感觉给没 ...

  6. 被培训机构坑了,面国企要求唱歌...谈谈我转型大数据的心酸历程

    前言 今天分享是是学习群的一个小伙伴,他本科是三本院校,研究生读了双非研究生,都是嵌入式方向.学习欲望很强烈,也一身正气,但在最早学习的时候被身边环境所蛊惑,认为非重点.非科班进不了好的公司,后面培训 ...

  7. C++入门——“为C补坑”

    C++入门 C++兼容C语言 入门就是补充一些C语言不支持的(给C语言补坑),为类和对象打基础 #include <iostream> using namespace std;int ma ...

  8. MySQL数据库操作补坑(一)数据类型

    目录 数据类型 数据类型介绍 1).整数类型 2).浮点类型和定点数类型 3).日期与时间型 4).字符串类型 5).二进制类型 如何选择数据类型 1).整数类型和浮点数类型 区别及选择 2).浮点数 ...

  9. 求求你们别再去培训机构学假的人工智能了,培训机构的人工智能培训的“坑”

    自从人工智能走入大家的视线,到今年新公布的七大"新基建",人工智能榜上有名.人工智能行业发展可以说是热火朝天,当然,导致了一些不合规的培训机构打着"打着人工智能的旗号&q ...

最新文章

  1. 按摩师-总预约时间最长
  2. Acid: 单网页检查页面,浏览器兼容性测试,浏览器好坏的标志
  3. php 接口继承接口
  4. 齐博cms任意登陆漏洞
  5. MySQL主从复制中关于AUTO_INCREMENT的奇怪问题
  6. 深度学习中的Attention总结
  7. java 枚举 映射_java – 如何将值映射到枚举?
  8. Dbgview - 签名无效
  9. 已解决-电脑端HP Scan扫描无反应无法扫描
  10. 中国省-市-县(区)三级城市数据(json和数组)
  11. OpenTCS 之 DefaultDispatcher 默认调度算法
  12. 点击程序不弹出界面,但有后台服务
  13. Android SDK是什么意思?
  14. 嵌入式软硬件模块化开发和工具性总结
  15. Android中图片压缩方案详解
  16. 项目实战:ASP.NET:B/S结构 个人空间相册、照片上传下载系统
  17. 「溪数科技」获逾5千万天使轮融资,开启智能运维加速模式!
  18. 使用谷歌(Chrome)浏览器截长图的方法
  19. 一个内存不能被written的问题
  20. 手把手教你读财报----银行业---第十课

热门文章

  1. 【网址收藏】VMware虚拟机安装Windows7
  2. 【视频】vue 插值表达式之三元运算符的使用
  3. 请简短说明一下你对AQS的理解
  4. Spring Boot之 Configuration Annotation Proessor not found in classpath解决方法
  5. springboot中的spring-session用mysql实现session共享实践
  6. 浅谈Android事件分发机制
  7. 【已解决】Linux下安装JDK
  8. 强化学习3——有模型(Model-base)与无模型(Model-free)RL的区别
  9. ZYNQ中断示例修改
  10. eclipse为什么导入不了awt_为什么选择javafx?