图论

HDOJ题目分类

你。 提交于 2020-02-21 07:22:40
1001 整数求和 水题 1002 C语言实验题——两个数比较 水题 1003 1、2、3、4、5... 简单题 1004 渊子赛马 排序+贪心的方法归并 1005 Hero In Maze 广度搜索 1006 Redraiment猜想 数论:容斥定理 1007 童年生活二三事 递推题 1008 University 简单hash 1009 目标柏林 简单模拟题 1010 Rails 模拟题(堆栈) 1011 Box of Bricks 简单题 1012 IMMEDIATE DECODABILITY Huffman编码 1013 STAMPS 搜索or动态规划 1014 Border 模拟题 1015 Simple Arithmetics 高精度计算 1016 Shoot-out 博弈+状态压缩DP 1017 Tour Guide 1018 Card Trick 简单题 1019 Necklace Decomposition 贪心 1020 Crashing Robots 模拟题 1021 Electrical Outlets 简单题 1022 Watchdog 简单题 1023 Taxi Cab Scheme 图论:最小路径覆盖--->最大二分匹配 1024 Pseudo-random Numbers 数论 1025 Card Game Cheater 简单题 1026

ACM-ICPC实验室20.2.19测试-图论

喜欢而已 提交于 2020-02-19 18:38:07
B.Harborfan的新年拜访Ⅱ 就是一道tarjan缩点的裸题。 建图比较麻烦 以后遇到这种建图,先用循环把样例实现出来,再对着循环写建图公式 #include<bits/stdc++.h> using namespace std; const int maxn=1014; vector<int> g[maxn]; string s1,s2; int N,M; int low[maxn]; int dfn[maxn]; int pos[maxn]; stack<int> st; int scc; int cnt; void tarjan (int x) { low[x]=dfn[x]=++cnt; st.push(x); for (int i=0;i<g[x].size();i++) { if (!low[g[x][i]]) { tarjan(g[x][i]); low[x]=min(low[x],low[g[x][i]]); } else if (!pos[g[x][i]])low[x]=min(low[x],dfn[g[x][i]]); } if (low[x]==dfn[x]) { scc++; while (1) { int u=st.top(); st.pop(); low[u]=low[x]; pos[u]=scc; if (u==x) break; } } }

入门——最短路(floyd, dijkstra)

冷暖自知 提交于 2020-02-19 09:16:22
今天讲图论基础和两种最短路算法。 老实说,我不觉的我能把最短路讲好,因为我主功不是图论,好久没有用了。本来只想找几篇博客放这里,但是发现现在的博客鱼龙混杂,感觉自己更应该讲好了。。。 首先要对图论有个大概的了解,尽管是刚入门,但是为了以后的学习还是要知道图论的基础名词的,我不是科班出身只能引用大佬的博客: https://blog.csdn.net/saltriver/article/details/54428685?utm_source=distribute.pc_relevant.none-task 。 了解了正统的图论以后,那么现在你只需要记住今天算法的应用范围就行:带有权的连通图,换句话说就是有很多点,这些点都有路能串起来并且这些路或者点是有数据的。我们今天讲的最短路算法就主要计算任意两点间的最短距离。最短路的算法有很多,常用的就有四个,分别是Floyd、dijkstra、bf 和spfa,在这里我们只学floyd和dijkstra,因为这两种算法的思想不仅能用在最短路上,在其他的时候也能用来偷分。另外两种算法选学,在处理特别复杂的图问题的时候,这两种算法因为更优的复杂度还是有很高的使用率的,不过学习的成本有点高,不适合初学。 零、存图 进行图论算法的第一步,就是把图存起来。存图的两种方式为邻接矩阵和邻接表。 邻接矩阵是建立一个二维数组,大小为所有点的数量+5

图论-网络流④-最大流解题①

て烟熏妆下的殇ゞ 提交于 2020-02-17 01:50:22
图论-网络流④-最大流解题① 上一篇: 图论-网络流③-最大流② 下一篇: 图论-网络流⑤-最大流解题② 参考文献: https://www.luogu.com.cn/problemnew/solution/P1231 大纲 什么是网络流 最大流(最小割) D i n i c Dinic D i n i c (常用) E K EK E K S a p Sap S a p F o r d − F u l k e r s o n Ford-Fulkerson F o r d − F u l k e r s o n (不讲) H L P P HLPP H L P P (快) 最大流解题 Start \color{#33cc00}\texttt{Start} Start End \color{red}\texttt{End} End 费用流 S p f a Spfa S p f a 费用流 B e l l m a n − F o r d Bellman-Ford B e l l m a n − F o r d 费用流 D i j k s t r a Dijkstra D i j k s t r a 费用流 z k w zkw z k w 费用流 费用流解题 有上下界的网络流 无源汇上下界可行流 有源汇上下界可行流 有源汇上下界最大流 有源汇上下界最小流 最大权闭合子图 有上下界的网络流解题

图论基本知识

こ雲淡風輕ζ 提交于 2020-02-16 14:28:45
本文主要参考于《离散数学及其应用》(傅彦 著)中的图论篇 图 图的基本概念 图的定义 一个 图(graph) 是一个序偶 < V , E > <V, E> < V , E > ,记为 G = < V , E > G = <V, E> G = < V , E > ,其中: (1) V = v 1 , v 2 , . . . , v n V = { v_1, v_2, ..., v_n} V = v 1 ​ , v 2 ​ , . . . , v n ​ 是有限非空集合, v i v_i v i ​ 称为 节点(nodal point) ,简称 点(point) , V V V 称为 节点集(nodal set) . (2) E E E 是有限集合,称为 边集(frontier set) , E E E 中的每个元素都有 V V V 中的节点对与之对应,称之为 边(edge) . 图的表示 图的集合表示 图的图形表示 图的矩阵表示 优点:便于用代数知识来研究图的性质,特别是便于用计算机来处理。 邻接矩阵(adjacency matrix) : 设图 G = < V , E > G = <V, E> G = < V , E > , 其中 V = v 1 , v 2 , . . . , v n V = {v_1, v_2, ..., v_n} V = v 1 ​ , v 2 ​ , . .

洛谷专题-较复杂图论I

你说的曾经没有我的故事 提交于 2020-02-15 00:19:18
P1268 树的重量 (思维题) 题意: 首先定义树的重量为数上每个边权的和,现在给你每个叶子结点之间的最短距离,让你求出树的重量 思路: 先定义叶子节点之间的距离为dis[u,v] 那么我们会先考虑只有两个节点的情况,那么答案就为dis[u,v] 当n=3,我们考虑将3号节点加入树中,由于每个节点都是叶子节点,那么3号节点只能由一条边连接至1与2的连线上 长度len = (dis(1,3)+dis(2,3)-dis(1,2))/2 n>3的情况也同理。枚举i,看看点n是不是从点1~i的路径上分叉出来的,求出的最小len就是要加到答案里面去的 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #define inf 0x3f3f3f3f using namespace std; const int maxn=35; int dis[maxn][maxn]; int main() { int n,x; while(scanf("%d",&n)&&n){ memset(dis,0,sizeof(dis)); for(int i=1;i<n;++i){ for(int j=i+1;j<=n;++j){ scanf("%d",&x); dis[i][j]=x,dis[j][i]=x; } }

【学习笔记】[图论]树的重心

安稳与你 提交于 2020-02-14 20:31:06
非严格定义:树上任意一点都可以为根。对于某一点,若以它为根,则它的所有子树大小尽可能接近。 性质: 树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个/多个重心,到他们的距离和一样。 把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上。 一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。 对于任意一棵树,叶子节点不可能是这棵树的重心。特别地,只有两个结点的树例外。 求解方法: 思考可以得出如下事实: 对于以任意一个结点作为根的所有最大子树中,以树的重心得出的最大子树最小。 所以,考虑用 DFS 遍历所有结点,每次求出以当前节点为根的最大子树的大小,记为 \(f_u\) 。设最终答案为 \(rt\) ,在遍历完某结点的所有儿子节点后,将求得的 \(f_u\) 与 \(f_{rt}\) 作比较,若小于,则令 \(rt=u\) 。 另外,还需要解决一个问题。如图: 记 \(size_u\) 为结点 \(u\) 的树的大小。如上图紫色数字所示。 不难发现,对于蓝色部分,只需要递归去扫一遍,把每棵子树的大小加起来就好了。了。但是,对于绿色部分,不难发现它原来属于红色结点的“父辈”。换而言之,我们无法通过递归的方式得出绿色部分的大小。 解决办法很简单:利用类似前缀和的思想,用整棵树的大小(记位 \(sum\) )减去除了“父辈

OI模板合集(数据结构、图论、数论)

跟風遠走 提交于 2020-02-11 00:13:13
本模板合集将持续更新 数据结构 并查集 编写次数:29 int fa[MAX]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } inline void merge(int x,int y){ register int a=find(x),b=find(y); if(a!=b)fa[a]=b; } int main(){ for(register int i=1;i<=n;++i)fa[i]=i; return 0; } 树状数组 BIT 编写次数:24 int Arr[MAX]; inline void Add(int x,int v){ while(x<=n){ Arr[x]+=v; x+=(x&-x); } } inline int Query(int x){ register int res=0; while(x){ res+=Arr[x]; x+=(x&-x); } return res; } 线段树 seg 编写次数:25 int tree[MAX<<2],tag[MAX<<2]; inline void pushup(int x){ tree[x]=tree[x<<1]+tree[x<<1|1]; } inline void push_down(int x,int l,int r,int v){ tag

ACM春季集训图论NOIP杂选题

十年热恋 提交于 2020-02-09 19:20:44
题目传送门: https://www.luogu.com.cn/problem/P3916 #include<iostream> #include<bits/stdc++.h> using namespace std; const int maxn=100010; int n,m,a[maxn]; vector<int> g[maxn]; void dfs(int x,int d){ if(a[x]) return; a[x]=d; for(int i=0;i<g[x].size();i++){ dfs(g[x][i],d); } } int main(){ int u,v; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>u>>v; g[v].push_back(u);//反向存储 } for(int i=n;i;i--) dfs(i,i); for(int i=1;i<=n;i++) printf("%d ",a[i]); cout<<endl; return 0; } 来源: https://www.cnblogs.com/ssxzwwsjz/p/12288237.html

搜索与图论——最小生成树和二分图(2)

帅比萌擦擦* 提交于 2020-02-08 18:45:27
接上篇 对最小生成树的相关算法进行的讲解 此篇讲的是二分图的有关算法 二分图 二分图有一个很重要的性质: 无向图G=<V,E>是二部图当且仅当G中无奇数长度的回路(环) 可以推出:无向图G=<V,E>是二部图当且仅当能被二染色没有矛盾地染一遍 二分图的判定 思路:运用染色性质 主函数中: for ( int i = 1 ; i <= n ; i ++ ) { if ( ! color [ i ] ) //若未被染色 { if ( ! dfs ( i , 1 ) ) //dfs返回false即是遇到了染色矛盾 { flag = false ; //false即无法形成二分图 break ; } } } dfs函数: bool dfs ( int u , int c ) { color [ u ] = c ; for ( int i = h [ u ] ; i != - 1 ; i = ne [ i ] ) //遍历所有邻点 { int j = e [ i ] ; if ( ! color [ j ] ) { if ( ! dfs ( j , 3 - c ) ) return false ; //c==1-->3-c==2,c==2-->3-c==1即对不同的相邻点赋不同值。若返回矛盾则返回矛盾 } else if ( color [ j ] == c ) return false ;