vis

树的遍历——DFS与BFS

扶醉桌前 提交于 2019-12-03 20:53:25
posted on 2019-08-28 16:45:21 A.树的遍历 题目描述 给定一棵 \(n\) 个节点的无根树(节点编号 \(0\) 至 \(n-1\) )和一个节点 \(x\) ,请以 \(x\) 号节点为根,做一次 DFS 与一次 BFS 。 输入格式 从标准输入读入数据。 第一行输入一个正整数 \(n\) ( \(1 \leq n \leq 200000\) ),代表这棵树的节点数目。 接下来 $ n-1 $ 行(行编号从 $ 1 $ 至 $ n-1 $),第 \(i\) 行输入一个正整数 $ a_i \((\) 0 \leq a_i \leq i $),代表第 \(i\) 个节点与第 $ a_i $ 个节点之间连有一条边。 最后一行输入 $ x \((\) 0 \leq x < n $),代表根节点编号。 输出格式 输出到标准输出。 输出 $ 2 $ 行,每行 $ n $ 个数,第 $ 1 $ 行代表 DFS 序,第 $ 2 $ 行代表 BFS 序。 注意:如果一个节点有多个儿子,那么应按照儿子编号递减的顺序去遍历。 样例1输入 7 0 1 0 0 1 4 1 样例1输出 1 5 2 0 4 6 3 1 5 2 0 4 3 6 解: #include <iostream> #include <cstdio> #include <cstring> #include

[模板]SPFA判负环

…衆ロ難τιáo~ 提交于 2019-12-03 20:19:39
目录 一、BFS法判负环 二、DFS法判负环 三、SPFA判正环 一、BFS法判负环 Code: #include<bits/stdc++.h> #define re register #define INF 0x3f3f3f3f using namespace std; int n,m; int first[8000],next[8000],go[8000],tot,cost[8000]; int dist[8000],vis[8000],add[8000]; inline void add_edge(int u,int v,int w){ next[++tot]=first[u]; first[u]=tot; go[tot]=v;cost[tot]=w; } inline void read(int &x){ x=0;int flag=1;char ch=getchar(); while(isdigit(ch)){if(ch=='-') flag=-1;ch=getchar();} while(!isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} x*=flag; } int SPFA(){ queue<int> q; for(int i=1;i<=n;i++){dist[i]=INF;vis[i]=0;} dist[1]=0

P5025 [SNOI2017]炸弹

我只是一个虾纸丫 提交于 2019-12-03 17:09:54
原题链接 https://www.luogu.org/problem/P5025 闲话时刻: 第一道 AC 的黑题,虽然众人皆说水。。。 其实思路不是很难,代码也不是很难打,是一些我们已经学过的东西凝合在一起,只要基础扎实的话,做出这道题目来说也就很简单了(不包括我); 题目大意: 有 n 个点,每个点可影响到它左右各 R [ i ] 范围内的点,并且影响到的点会产生连锁反应,求每个点能影响到多少个点; 题解: 一个很简单的思路: 向每个炸弹爆炸范围内的其他炸弹连一条 有向边 < u , v >,表示 u 能炸到 v,最后我们从每个点开始跑 dfs,看看能到达多少个点就好了; 但是。。。 这样连边的话,最劣情况下会连 n 2 条边,看一眼 n 的范围: N ≤ 5 0 0 0 0 0,嗯,显然不行 ~o(* ̄▽ ̄*)o; 考虑建边优化: 不难想到一个炸弹的爆炸范围是一个长度为 2 * R [ i ] 的区间,这个区间内的所有炸弹都会被引爆,因此被引爆的炸弹也是一个连续的区间; 区间操作?你想到了什么? 线段树优化建边 假如说一个炸弹 x 能炸到第 2~6 个炸弹,考虑怎么建边: 一般操作: 线段树优化建边: 建了 5 条边?看我的! 我们发现,这种建边方式只需要建 ⌈ log 2 5 ⌉ = 3 条边; 看了上面的图,应该对 线段树优化建边 有了一个初步的认识了:

数论题目小记

吃可爱长大的小学妹 提交于 2019-12-03 16:57:49
素数个数 【题目描述】求n到n+m内的素数个数 【解题报告】 “数论题目有时复杂度看着很大,实际上并没有那么大” 详见代码 #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e6 + 3; ll n, m, pr[N], tot, s[N]; bool vis[N]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%lld%lld", &n, &m); memset(vis, 0, sizeof vis); tot = m + 1; for (ll i = 2; i <= 1e6 && i <= n + m; i++) for (ll j = (n / i) * i; j <= n + m; j += i) //保证跳到的都是合数 if (j >= n && j != i && !vis[j - n]) { vis[j - n] = 1; tot--; //素数的个数等于总数-合数 } printf("%lld\n", tot); } return 0; } 视野 【传送门】 http://oj.ipoweru.cn/problem/70014 【题目大意】给定正整数 \(C\) ,问从 原点

1428 漫步校园(记忆化搜索)

筅森魡賤 提交于 2019-12-03 16:57:42
漫步校园 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5607 Accepted Submission(s): 1756 Problem Description LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划分为n*n个小方格,代表各个区域。例如LL居住的18号宿舍位于校园的西北角,即方格(1,1)代表的地方,而机房所在的第三实验楼处于东南端的(n,n)。因有多条路线可以选择,LL希望每次的散步路线都不一样。另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…)。现在他想知道的是,所有满足要求的路线一共有多少条。你能告诉他吗? Input 每组测试数据的第一行为n(2=<n<=50),接下来的n行每行有n个数,代表经过每个区域所花的时间t(0<t<=50)(由于寝室与机房均在三楼,故起点与终点也得费时)。 Output 针对每组测试数据,输出总的路线数(小于2^63)。 Sample Input 3 1 2 3 1 2 3 1 2 3 3 1

数论题目小记

女生的网名这么多〃 提交于 2019-12-03 16:31:39
素数个数 【题目描述】求n到n+m内的素数个数 【解题报告】 “数论题目有时复杂度看着很大,实际上并没有那么大” 详见代码 #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e6 + 3; ll n, m, pr[N], tot, s[N]; bool vis[N]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%lld%lld", &n, &m); memset(vis, 0, sizeof vis); tot = m + 1; for (ll i = 2; i <= 1e6 && i <= n + m; i++) for (ll j = (n / i) * i; j <= n + m; j += i) //保证跳到的都是合数 if (j >= n && j != i && !vis[j - n]) { vis[j - n] = 1; tot--; //素数的个数等于总数-合数 } printf("%lld\n", tot); } return 0; } 来源: https://www.cnblogs.com/phemiku/p/11802954.html

[笔记乱写]关于欧拉路

自作多情 提交于 2019-12-03 11:56:29
发现这个小东西虽然很简单但是考一次挂一次 A.定义 欧拉路:图中任意一个点开始到图中任意一个点结束,且通过的每条边只被通过一次的路径。 欧拉回路:同上,不过起点与终点相同。 B.判定 这里只以欧拉路为例。 无向图:对于一张无向图,当且仅当图联通且奇点数为0或2时,存在一条能遍历整张图的欧拉路。如果奇点数为2,那么这两个点应当作为欧拉路的起点和终点,否则任意一点都可作为欧拉路的起点和终点。 有向图:对于一张有向图,当且仅当图联通且有0个或2个点的入度不等于出度。如果有2个点,那么这两个点当中一个必须入度=出度-1作为起点,另一个必须出度=入度-1作为终点,否则任意一点都可作为欧拉路的起点和终点。 C.算法 一般使用Hierholzer算法解决欧拉路问题,时间复杂度为$O(n+m)$。 首先来看优化前的$O(nm)$版本: void dfs(int x) { for(int i=head[x];i;i=nxt[i]) { if(vis[i])continue; int y=to[i]; vis[i]=vis[i^1]=1;//The original edge_num should be 1. dfs(y,i); } st[++top]=x; } 很弱智是吧? 可能第一次看会觉得它不能保证形成包括所有边的方案,然而最后把点入栈的过程其实就是“拼凑”多条子欧拉路的过程。

洛谷P1084 疫情控制

最后都变了- 提交于 2019-12-03 11:55:28
题目 细节比较多的二分+跟LCA倍增差不多的思想 首先有这样一个贪心思路,深度越低的检查点越好,而最长时间和深度具有单调性,即给定时间越长,每个军队能向更浅的地方放置检查点。因此可以考虑二分时间,然后判断军队是否可以放置在控制疫情的地方。 但是有的军队需要先满足自己当前所在的节点,然后此节点如果有多个军队,其他军队跳到1节点,再跳到1节点的其他子树,这里又有一个贪心策略,就是每个军队跳到1的剩余时间:二分的当前时间减去到1节点的距离越大,就要跳到1的另一个子树里据1最远的点,这样才能更好地使得控制疫情。 #include <bits/stdc++.h> #define N 1001001 using namespace std; struct edg { int to, nex, len; }e[N]; struct tem { int id, len; }a[N], b[N]; int n, m, cnt, lin[N], vis[N], vis2[N], army[N], dep[N], fa[N][19], dis[N][19];//fa[i][j]表示军队向上跳j次所到达的位置,dis表示此时所用的时间。 //vis表示该点包括的叶子节点是否被完全覆盖 bool cmp(tem x, tem y) { return x.len < y.len; } inline void

A - 奔小康赚大钱(KM算法)

丶灬走出姿态 提交于 2019-12-03 11:46:24
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。 这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。 另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的). Input输入数据包含多组测试用例,每组数据的第一行输入n,表示房子的数量(也是老百姓家的数量),接下来有n行,每行n个数表示第i个村名对第j间房出的价格(n<=300)。 Output请对每组数据输出最大的收入值,每组的输出占一行。 Sample Input 2 100 10 15 23 Sample Output 123这是KM算法的一道模板题KM算法就是的最大权匹配(与匈牙利算法不同的是KM需要考虑权值)依旧是男女配对https://www.cnblogs.com/wenruo/p/5264235.html(请参考这篇博客,很详细

递归欧拉路模板。当前弧优化。

我怕爱的太早我们不能终老 提交于 2019-12-03 11:34:47
#include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;++i) #define LL long long #define pf(a) printf("%d ",a) #define phn puts("") using namespace std; int read(); /** 当前弧优化,否则会卡成m^2. 没有固定起点时可以随便选,但必须有边与他相连,不能直接用1.*/ #define N 400010 int T,n,m; int chu[N],ru[N],du[N],to[N<<1],fir[N<<1],id[N<<1],head[N],cnt; void add(int x,int y,int ID){to[++cnt]=y;fir[cnt]=head[x];head[x]=cnt;id[cnt]=ID;} int sta[N<<1],vis[N<<1],top; void dfs1(int x){ for(int i=head[x];i;){ while(i&&vis[i])i=fir[i]; if(i){ vis[i]=1;head[x]=fir[i]; dfs1(to[i]); sta[++top]=id[i]; i=head[x]; } } } void dfs2(int x){ for(int i