dfs

HDU 1561 The more, The Better【树形DP】

只谈情不闲聊 提交于 2020-03-03 22:20:55
Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗? Input 每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。 Output 对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。 Sample Input 3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0 Sample Output 5 13 转:分析: 状态 dp[i][j] 为以 i 为根节点,选出 j 个节点的最大价值(包括 i 这个节点) 转移方程:dp[i][j]=max(dp[i1][j1]+dp[i2][j2]+....+dp[ik][jk])+a[i] j1+j2+...+jk=j

hdu 4751(dfs染色)

六月ゝ 毕业季﹏ 提交于 2020-03-03 21:40:12
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4751 思路:构建新图,对于那些两点连双向边的,忽略,然后其余的都连双向边,于是在新图中,连边的点是能不在同一个图中的,于是我们可以用dfs染色的方法来判断是否存矛盾。 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 int map[111][111]; 9 int color[111]; 10 int n; 11 vector<vector<int> >g; 12 13 bool dfs(int u,int father,int state) 14 { 15 color[u]=state; 16 for(int i=0;i<g[u].size();i++){ 17 int v=g[u][i]; 18 if(v==father)continue; 19 if(color[v]&&color[u]==color[v]){ 20 return false; 21 }else if(!color[v]&&!dfs(v,u,3-state)){ 22 return false; 23 }

Codeforces 555E. Case of Computer Network 题解

情到浓时终转凉″ 提交于 2020-03-03 17:13:29
题目链接: E. Case of Computer Network 题目大意:给定一张 \(n\) 个点 \(m\) 条边的无向图( 图不一定联通 ),给定 \(q\) 组有向点对 \((s_i,t_i)\) ,问是否有一种边的定向方式,使得 \(q\) 组点对都可以从 \(s_i\) 到达 \(t_i\) 。 题解: 不会求边双的菜鸡自闭了。 这一题,如果整个图是一个边双联通分量的话,因为每两个点之间都有至少两条路径,一定符合条件。那么很明显可以想到可以直接将原图边双缩点,最后得到的结果就是一片森林,如果有任意一组 \((s_i,t_i)\) 不在同一棵树内,直接输出 No 即可,对于另外的限制,通过在在树上打标记来实现,具体操作就是:令 \(lca_i=\text{LCA}(s_i,t_i)\) ,那么就是从 \(s_i\) 到 \(lca_i\) 的边全部向上,从 \(lca_i\) 到 \(t_i\) 的边全部向下,所以用两个标记 \(tag_{1,u},tag_{2,u}\) ,一个 \(u\) --> \(fa_u\) 边的方向向上的点对数,另一个表示 \(fa_u\) --> \(u\) 边的方向向下的点对数,所以,在一个点上如果 \(tag_{1,u}>0\text{且}tag_{2,u}>0\) 时,很明显出现矛盾,输出 No ,如果所有的点都合法,那么输出

LeetCode:473 火柴拼正方形 dfs+剪枝

白昼怎懂夜的黑 提交于 2020-03-03 16:33:29
还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。 输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。 示例 1: 输入: [1,1,2,2,2] 输出: true 解释: 能拼成一个边长为2的正方形,每边两根火柴。 示例 2: 输入: [3,3,3,3,4] 输出: false 解释: 不能用所有火柴拼成一个正方形。 注意: 给定的火柴长度和在 0 到 10^9之间。 火柴数组的长度不超过15。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/matchsticks-to-square 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 思路 其实就是有四个容量为len的桶,要把它们装满,并且用上全部的火柴,那么对于每个火柴都有4种选择,暴力枚举所有的选择即可,复杂度为O(4 n ),但是这么做OJ上超时,需要加入两个剪枝: 如果搜索的过程中,遇到某个桶的容量超过len,那么这种情况以及其之和的衍生情况都不成立,直接返回false 在容量足够的情况下,优先考虑最大的火柴,也就是对数组降序排序,这样有助于更快发现最优解 比如最后一个火柴长度超出len

【C++】树型动态规划

Deadly 提交于 2020-03-03 10:28:28
树型动态规划 摘要 例1 没有上司的舞会 题目描述 输入描述 输出描述 样例输入 样例输出 思路 1 定义状态: 2 转移方程: 3 初始值: 4 答案: 代码 例2 数字转换 题目描述 输入描述 输出描述 样例输入 样例输出 样例说明 数据范围 代码 例3 二叉苹果树 题目描述 输入描述 输出描述 样例输入 样例输出 数据范围 思路 1 状态定义 2 转移 3 初始 4 答案 代码 例4 选课 题目描述 输入描述 输出描述 样例输入 样例输出 数据范围 思路 1 状态: 2 转移: 3 初始值: 4 答案: 代码 摘要 之所以这样命名树规,是因为树规的这仙特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系。利用这仙特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的程序。而深搜的特点,就是“不撞南墙不回头”。这仙点在之后的文章中会详细的介绍。 关键字:树,动态规划,递归 例1 没有上司的舞会 Luogu-1352 链接: https://www.luogu.com.cn/problem/P1352 我记得原题是“Ural大学” 还是给出原题吧。 题目描述 Ural大学有N个职员,编号为1到N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大

C语言程序设计100例之(31):全排列问题

瘦欲@ 提交于 2020-03-03 09:40:20
例31 全排列问题 题目描述 输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。 输入格式 n(1≤n≤9) 输出格式 由1~n组成的所有不重复的数字序列,每行一个序列。序列中每个数字占5个宽度。 输入样例 3 输出样例 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 (1)编程思路。 采用递归的方法来生成全排列。 (2)源程序。 #include <stdio.h> int a[9],flag[10]={0}; void dfs(int pos,int n) { if (pos==n) // 已有n个数 { for (int i=0;i<n;i++) printf("%5d",a[i]); printf("\n"); } else { for(int i=1;i<=n;i++) { if(flag[i]) continue; a[pos]=i; flag[i]=1; dfs(pos+1,n); flag[i]=0; } } } int main() { int n; scanf("%d",&n); dfs(0,n); return 0; } 习题31 31-1 选书 本题选自洛谷题库 (https://www.luogu.org/problem/P1657) 题目描述 学校放寒假时,信息学奥赛辅导老师有1,2

C语言程序设计100例之(32):组合问题

元气小坏坏 提交于 2020-03-03 09:39:13
例32 组合问题 题目描述 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。 例如n=5,r=3,所有组合为:123,124,125,134,135,145,234,235,245,345。 输入格式 一行两个自然数n,r(1<n<21,1≤r≤n)。 输出格式 所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。 输入样例 5 3 输出样例 1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5 (1)编程思路。 用递归来完成。 设函数void dfs(int pos,int num)表示为第pos(0≤pos≤r-1)个数取值,取值可以为num~n之一。显然,若r-pos>n-num+1,则后面剩下的数不够,直接剪枝;否则,在num~n中取一个数i(num≤i≤n)赋给a[pos],继续为下一个位置pos+1取数,即递归调用函数dfs(pos+1,i+1)。 (2)源程序。 #include <stdio.h> int a[21],n,r; void dfs(int pos,int num) { if (pos==r) // 已有r个数 { for

05.图与树的面试题目精讲

这一生的挚爱 提交于 2020-03-03 08:15:42
目录 图论简介 面试题总体分析 一些例题: 例1.给定二叉树的前序遍历和中序遍历,构造二叉树 LC-105 例2.二叉树的高度、最小深度、二叉搜索树(BST)判断、对称判断、平衡判断 【用同一个递归框架解决】 例3.二叉树与链表转换 例4.无向图复制 例5.直角路线遍历棋盘 总结 图论简介 面试题总体分析 图: 连通性(割点、边)、 最小生成树 、最短路 、 搜索(BFS、DFS) 、 欧拉回路 、 哈密尔顿回路 、 拓扑排序 树: 树的定义与判断 、、 平衡,二叉搜索树、最大(小)深度 、最近公共祖先(LCA) 一些例题: 例1.给定二叉树的前序遍历和中序遍历,构造二叉树 LC-105 分析:前序遍历的第一个节点是根节点,在中序遍历中找到根节点,并把中序遍历分为左子树+右子树 注意 下标范围 class Solution{ public: TreeNode * dfs(vector<int> &preorder, vector<int> &inorder,int pre, int in, int len){ if(len==0) return null; TreeNode * root=new TreeNode(preorder[pre]); //树根节点为前序遍历的第一个节点 int i; for(i=in;inorder[i]!=preorder[pre];i++); /

题解 P2661 【信息传递】

大憨熊 提交于 2020-03-03 07:25:52
这题 由于每个人只能告诉一个人,所以每个点的出度为1。找最小环。 坑点: 图不一定是连通图 故不能只用一遍bfs/dfs。 下面讲我的思路 三个数组 \(next,vis,dep\) ; \(next_i\) 记录第i位同学传递的人 \(vis_i\) 记录当前点是否访问和是哪一次访问 \(dep_i\) 记录第i个点在它的访问里的深度 当 \(dfs\) 时出现点已被访问,判断 是当前 \(dfs\) 访问过的点 \(then\) 更新答案 否则不考虑 #include <cstdio> using namespace std; int n,ans; int vis[200005],dep[200005],next[200005]; int main(){ ans=1<<17; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&next[i]); for(int i=1;i<=n;i++) if(vis[i]==0){ int dfs=0,j; for(j=i;vis[j]==0;j=next[j])vis[j]=i,dep[j]=++dfs; if(vis[j]==i && dfs-dep[j]<ans)ans=dfs-dep[j]; } printf("%d\n",ans+1); return 0; } 点个赞吧 来源:

codeup DFS or BFS?

与世无争的帅哥 提交于 2020-03-03 07:23:24
题目描述 说好了,题目不黑人。 给你一个8*8的矩阵,你的初始位置是左下角方格(用'U’表示),你的目标位置是右上角的方格(用'A'表示),其余的62个方格,如果是'.',表示这个方格为空,如果是'S',表示这个方格有一块大石头。好了现在你开始从左下角出发,每次可以往上,下,左,右,左上,右上,左下,右下移动一个方格,或者你可以原地不动,一共九个动作方式,在你做完一个动作后,所有的大石头会往下掉一个方格(如果一个大石头的位置是(x,y),那下一秒是(x+1,y),不过如果它已经在最下面的一排了,那它就会掉出矩阵,不再出现),请注意,任一时刻,你不能和某一个大石头处在同一个方格,否则石头会把你XX掉。 现在的问题就是:你能从左下角安全抵达右上角么? 如果能,输出“Yes”,反之,“No”。 输入 T->测试数据组数(T)。 对于每组数据,输入一个8*8的矩阵,其后有一空行。描述如上。 输出 对于第i组数据,请输出 Case #i: s(s是一个字符串,如果可以到达,则s为“Yes”,反之“No”) 样例输入 Copy 2 .......A ........ ........ ........ ........ ........ ........ U....... .......A ........ ........ ........ ........ .S...... S......