vis

SPFA算法——最短路径

感情迁移 提交于 2020-01-19 15:18:04
粗略讲讲SPFA算法的原理,SPFA算法是1994年西安交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n; //表示n个点,从1到n标号 int s,t; //s为源点,t为终点 int d[N]; //d[i]表示源点s到点i的最短路 int p[N]; //记录路径(或者说记录前驱) queue <int> q; //一个队列,用STL实现,当然可有手打队列,无所谓 bool vis[N]; //vis[i]=1表示点i在队列中 vis[i]=0表示不在队列中 几乎所有的最短路算法其步骤都可以分为两步 1.初始化 2.松弛操作 初始化: d数组全部赋值为INF(无穷大);p数组全部赋值为s(即源点),或者赋值为-1,表示还没有知道前驱 然后d[s]=0; 表示源点不用求最短路径,或者说最短路就是0。 将源点入队;     (另外记住在整个算法中有顶点入队了要记得标记vis数组,有顶点出队了记得消除那个标记) 队列+松弛操作 读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新,另外,如果点v没有在队列中,那么要将点v入队(记得标记),如果已经在队列中了,那么就不用入队 以此循环,直到队空为止就完成了单源最短路的求解 SPFA可以处理负权边 定理:

2017 Chinese Multi-University Training, BeihangU Contest

橙三吉。 提交于 2020-01-19 11:13:46
2017 Chinese Multi-University Training, BeihangU Contest Add More Zero 思路:log10(2^m) = m*log10(2) 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<int, pii> #define puu pair<ULL, ULL> #define pdd pair<long double, long

L3-007 天梯地图

限于喜欢 提交于 2020-01-19 02:24:39
本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。 输入格式: 输入在第一行给出两个正整数 N (2 ≤ N ≤ 500)和 M ,分别为地图中所有标记地点的个数和连接地点的道路条数。随后 M 行,每行按如下格式给出一条道路的信息: V1 V2 one-way length time 其中 V1 和 V2 是道路的两个端点的编号(从0到 N -1);如果该道路是从 V1 到 V2 的单行线,则 one-way 为1,否则为0; length 是道路的长度; time 是通过该路所需要的时间。最后给出一对起点和终点的编号。 输出格式: 首先按下列格式输出最快到达的时间 T 和用节点编号表示的路线: Time = T: 起点 => 节点1 => ... => 终点 然后在下一行按下列格式输出最短距离 D 和用节点编号表示的路线: Distance = D: 起点 => 节点1 => ... => 终点 如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。 如果这两条路线是完全一样的,则按下列格式输出: Time = T;

一本通基础篇图论

我的梦境 提交于 2020-01-18 21:19:43
1341 一笔画问题 1 #include <cstdio> 2 #include <algorithm> 3 #include <stack> 4 using namespace std; 5 const int MAXN = 110000,MAXM = 510000; 6 stack <int> stk; 7 int head[MAXN],ind[MAXN]; 8 int to[MAXM],nxt[MAXM],idx[MAXM]; 9 int cnt,n,m; 10 void add(int x,int y,int i) 11 { 12 nxt[++cnt] = head[x]; 13 to[cnt] = y; 14 head[x] = cnt; 15 idx[cnt] = i; 16 } 17 void dete(int x,int y) 18 { 19 if (head[x] == y) 20 { 21 head[x] = nxt[y]; 22 return; 23 } 24 for (int i = head[x];i;i = nxt[i]) 25 if (nxt[i] == y) 26 { 27 nxt[i] = nxt[y]; 28 return; 29 } 30 } 31 void dfs(int x) 32 { 33 for (int i = head[x];i

题解——Acwing.342 道路与航线

左心房为你撑大大i 提交于 2020-01-18 08:25:16
说在前面   首先这题单纯从数据出发的话,直接做SPFA,加点优化,SLF或者LLL的话是可以直接过的。   但是,本着 科学严谨的态度 ,极其不推荐使用这种投机取巧的偷懒方式。而且如果数据是特殊构造的话,就算加了优化也一样会被卡。故此处介绍正解。 算法介绍 算法描述:   考虑到本题有个非常好的性质:有向边必然无环。   先不考虑有向边,则所有无向边加点集构成的图就是数个连通块。   考虑有向边,将每个连通块看成点,每条有向边就是这些点之间的连边,则整张图构成一张有向无环图,可以直接拓扑排序遍历。   对于每个连通块内部,直接做Dijkstra即可。 算法流程:   先读入无向边,然后处理连通块,记录每个点所属的连通块编号以及每个连通块所包含的所有点。   再读入有向边,记录每个连通块的入度。   先找到入度为0的连通块,然后开始拓扑排序。   对于遍历到的每一个连通块,做一遍Heap_Dijkstra。在进行松驰操作时,判断两点是否在同一个连通块内,若是,则将其放入Heap中,否则将所指向的点所属连通块入度减1,然后将其放入拓扑队列中即可。 时间复杂度分析:   连通块处理和拓扑排序都是线性的,整个算法时间上的瓶颈就在于Dijkstra。   设连通块x内点数为nx,边数为mx。   则所有Dijstra的总时间为:m1logn1+m2logn2+……+mslogns<

ACM数论模板

半腔热情 提交于 2020-01-18 05:38:07
w2w原创 1. 欧几里得定理 int gcd(int a, int b){ return b==0?a:gcd(b, a%b); } 2. 扩展欧几里得 (求ax+by = gcd(a,b)的特解) void e_gcd(LL a, LL b, LL &d, LL &x, LL &y){ if(b==0){ x = 1; y = 0; d = a; } else{ e_gcd(b, a%b, d, y, x); y-= x*(a/b); } } 3. 中国剩余定理 同余方程组 x ≡ a1(mod m1) x ≡ a2(mod m2) ... ... x ≡ ak(mod mk) 方程组所有的解的集合就是: x1 = N1*a1 + N2*a2 + ... + Nk*ak 其中 Ni mod mi = 1,Ni = ai * ti , 可用欧几里得扩展定理求 ti. 其中M = m1*m2*m3····*mn; //互质版   #include <iostream> using namespace std; //参数可为负数的扩展欧几里德定理 void exOJLD(int a, int b, int &x, int &y){ //根据欧几里德定理 if(b == 0){//任意数与0的最大公约数为其本身。 x = 1; y = 0; }else{ int x1, y1;

AC自动机【模板】+经典例题

﹥>﹥吖頭↗ 提交于 2020-01-17 23:54:09
AC自动机模板 经典例题 Keywords Search HDU - 2222 【求目标串中出现了几个模式串】 【(注意:模式串可能会重复)】 模板: 1 const int maxn=26; 2 struct Trie 3 { 4 int next[500010][maxn]; 5 int fail[500010],end[500010]; 6 int root,L; 7 int newnode() //初始化 8 { 9 for(int i=0;i<26;i++) 10 next[L][i]=-1; 11 end[L++]=0; 12 return L-1; 13 } 14 15 void init()//初始化 16 { 17 L=0; 18 root=newnode(); 19 } 20 void insert(char s[])//构造树trie 21 { 22 int len=strlen(s); 23 int now=root; 24 for(int i=0;i<len;i++) 25 { 26 if(next[now][s[i]-'a']==-1) 27 next[now][s[i]-'a']=newnode(); 28 now=next[now][s[i]-'a']; 29 } 30 end[now]++; 31 } 32 33 void build()/

P2296 寻找道路

本秂侑毒 提交于 2020-01-17 09:06:37
链接: Miku -------------------------------------------- 一道很好的bfs,dfs混合练手题 -------------------------------------------- 这一道题看第一眼:愚蠢的bfs求最短路,有什么难的! 然后看见了一堆附加条件: 1 路径上的所有点的出边所指向的点都直接或间接与终点连通。 2 在满足条件11的情况下使路径最短 Ac 等等,与终点联通?难道我们要把每一个点dfs能不能行吗? 然而你想一想,如果你能从这个点走到终点,那么倒着走不久走回来了? (然而这是有向图额) 那么就建反图,dfs所有的能到终点的点 void dfs(int now){ if(vis[now]) return ; vis[now]=1; for(int i=h2[now];i;i=e2[i].ne){ dfs(e2[i].to); } } dfs ------------------------------------------- 预处理结束,重新看一下条件1,好吧,还有一步 预处理 for(int i=1;i<=n;++i){ int f=1; for(int j=h1[i];j;j=e1[j].ne){ if(!vis[e1[j].to]){ f=0; break; } } if(!f){ vis2[i]=1;

noip模拟赛 都市

烈酒焚心 提交于 2020-01-17 02:57:08
分析:是一道非常有意思的题,30分的暴力的话枚举每个位置是什么数,然后排个序,用map判一下重就好了,比较麻烦. 满分做法显然不可能讨论每个位置所有的情况,肯定是有规律的,现将这n*(n-1)/2个数排序,假设N个数组成的排列是a1,a2,......,aN,并且a1≤a2≤......≤aN.那么最小的那个和肯定是a1 + a2,次小的那个和肯定是a1 + a3,第三小的就不好确定了,如果能把a2 + a3给求出来,那么就能把a1,a2,a3给解出来,所以枚举a2+a3是哪一个,把a1+a2,a2+a3,a1+a3给求出来后从原数组中删掉,那么剩下的最小的数就是a1+a4,a4可以解出来,再把a2,a3与a4相加,把得到的数给删掉,再对a5进行同样的操作,就能得到整个序列了,所以枚举a2+a3的位置,并check一下就好了. check的时候要先判断这个ai+a1在原数组中存不存在,是否都已经被占用了,要判断好所有的情况才行. 30分暴力: #include <cstdio> #include <map> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n, cnt, a[20], flag[20], ans,tot,tag[20]; int p[20]

二分图详解及总结

雨燕双飞 提交于 2020-01-16 18:47:35
二分图:   二分图中,顶点可以分为两个集合,每一条边的端点都分别位于这两个集合。 二分图的判定:   可以利用Bfs或者Dfs进行黑白染色,共享一条边的两点异色,检查一下是否存在矛盾即可。     相关题目: Hdu 2444 The Accomodation of Students        Hdu 5313 Bipartite Graph bfs代码:    1 void bfs (int s) 2 { 3 int p, q, zreo, one, num; 4 queue <int> Q; 5 zreo = 1; 6 one = vis[s] = 0; 7 Q.push(s); 8 while (!Q.empty()) 9 { 10 p = Q.front(); 11 Q.pop(); 12 num = (vis[p] + 1) % 2; 13 for (int i=0; i<G[p].size(); i++) 14 { 15 q = G[p][i]; 16 if (vis[q]!=-1 && num != vis[q]) 17 flag = 1; 18 if (vis[q]==-1) 19 { 20 Q.push(q); 21 vis[q] = num; 22 if (num == 0) 23 zreo ++; 24 else 25 one ++; 26 } 27 }