图论总结与索引

  持续更新...

二分图:可分为两个互不相交的子集,且所有边的两个顶点均不在一个集合里,等价于不包含奇环

    1.二分图判定/构造:$DFS$染色即可,

  :*自环度数会记录两次,无向图度数和为边数2倍

  :所有点入度=出度

  匹配:一些边,任意两条边没有公共定点且无自环,被访问过的点成为被匹配,最大匹配时,任意添加一条边均破坏性质

  完美匹配:覆盖所有点的匹配

    1.二分图最大匹配:匈牙利算法/DInic最大流,

    2.二分图完美匹配/最小权值匹配:KM算法/费用流

    3.二分图多重匹配:每个点可以成为多个边的顶点 Dinic最大流

    4.一般图匹配:带花树算法

    5.一般图完美匹配

    6.稳定婚姻问题:propose-and-reject algorithm 模板

  点覆盖:覆盖所有边的点集

    1.二分图最小点覆盖:二分图最小点覆盖数=最大匹配数 König定理证明

    2.一般图最小顶点覆盖:NPC问题,具体分析

  边覆盖:覆盖所有点的边集

    1.二分图最小边覆盖:二分图最小边覆盖=点数-最大匹配数,下面是证明:

贪心的选一组最大匹配的边加入集合,对于剩下的每个未匹配的点,随便选一条与之关联的边加入集合,
得到的集合就是最小边覆盖,
所以:最小边覆盖=最大匹配+图中点的个数-2*最大匹配=图中点的个数-最大匹配

  路径覆盖:一些路径,覆盖所有点

    1.二分图最小路径覆盖:点数-最大匹配,如下:

对于G中每一个节点x,建立节点x1,x2。
若x- >y存在边,则x1与y2之间连一条无向边,求这个二分图的最大匹配数即可。

证明如下:
首先,若最大匹配数为0,则二分图中无边,也就是说有向图G中不存在边,那么
显然:最小路径覆盖=|G|-最大匹配数=|G|-0=|G|。

若此时增加一条匹配边x1--y2,则在有向图|G|中,x、y在同一条路径上,最小路径覆盖数减少一个。

继续增加匹配边,每增加一条,最小路径覆盖数减少一个,则公式:最小路径覆盖=|G|-最大匹配数得证。

    2.一般图最小路径覆盖:NPC问题,具体分析

  独立集:一个点集,任意两点不相连

    1.任何图上,最大独立集+最小点覆盖=点数

    2.二分图最大独立集:点数-最大匹配数

  最大团:一个点集,任意两点间相连

    1.二分图最大团:二分图最大团等价于原图补图的最大独立集,因此二分图最大团=点数-补图的最大匹配 NPC问题

    2.一般图的最大团/极大团:Bron–Kerbosch算法,

    3.极大团计数:BK算法变形

  连通性:无向图中两个顶点$u$和$v$连通,当且仅当从$u$到$v$有一条路径,连图图意味着任意两点皆连通

      有向图弱连通意味着如果把有向边替换为无向边则为连通图,强连通则意味着任意两点间皆可以互相到达

  连通块/强连通分量:一个连通的子图,且不是任意其他连通子图的子集

    1.求有向图强连通分量/无向图边双连通分量:tarjan算法 复杂度$O(V+E)$

    2.2-SAT:(Satisfiability) 2-完美问题 k-sat问题的简化,k>2时NP完全,只能指数级搜索

     给一堆01变量,再给出一些关系,问一组解,转化为连通性问题求解,参考

  点割:一个点集,删除之后会导致图不连通

  割点:删除后会导致图不连通的单个点,若无向连通图无割点,则任意两点之间都存在点集互不相交的路径(点双连通)

    1.求割点:tarjan

  桥:删除后会导致图不连通的单个边,若无向连通图无桥,则任意两点间存在边集不相交的路径(边双连通)

    1.求桥:tarjan

  哈密顿路:遍历所有点恰好一次的路径,哈密顿回路是遍历所有点一次后,回到起点的哈密顿路,竞赛图有奇数条哈密顿路,n阶无向图完全图有$/frac {(n-1)!}{2}$个哈密顿路,n阶有向图有$(n-1)!$个哈密顿环,$n$阶的简单图含有哈密顿图的充分条件是任意不相邻的顶点去度数之和大于等于$n$

    1.找哈密顿路/环:NP完全问题

  欧拉路:恰好经过每个边一次的路径

      有向图当且仅当图弱连通且所有顶点入度等于出度,存在欧拉回路

      有向图当且仅当图弱连通的,且除了2个顶点一个入度比出度多1,一个出度比入度多1其余入度均等于出度,存在欧拉路径

      无向图当且仅当图连通,且所有点的度数为偶数

      无向图当且仅当图连通,且除了两个点度数为奇数外,所有点的度数为偶数,也等价于可以被分解为若干不相交的环

      1.存在欧拉路径/回路:并查集+度数

      2.无向图/有向图寻找欧拉路径/回路:Fleury算法,Hierholzer算法

      3.混合图寻找欧拉路径/回路:转化为最大流问题,Dinic算法,复杂度$O(V^{2}E)$ 

  最短路:两点间的最短路径

      1.求最短路

      floyd:可以获得任意两点间的最短路,空间复杂度$O(V^2)$时间复杂度$O(V^3)$

      SPFA/Bellman-Ford:单源最短路, 空间复杂度$O(V+E)$,时间复杂度$O(VE)$

      dijkstra单调队列优化:单源最短路,空间复杂度%(V+E+log(V))$ 时间复杂度$O((E + V) log(V))$,只适用于非负权图

      2.差分约束系统:给出一些变量之间的大小关系,求解关系互相覆盖后的解域,转化为图论模型,用SPFA算法求解

  :一个无向,连通,无环,简单的$n$阶图,且删除任意一条边均导致图不连通,任意两点均有唯一的路径,并包含$n-1$条边

    树中任意3点,两两间的路径必有一个交点

    1.求树的直径:两次$dfs$,第一次从任意点出发,找到最远的点,第二次从该点出发找到另一个最远点,两点的唯一路径则为树的直径

int dfs(int now) {
	for(int i=head[now];i;i=e[i].next)
		if(!dis[e[i].to]) {
			dis[e[i].to]=dis[now]+1;
			dfs(e[i].to);
		}
}
int solve(){
	int pos=1;
	memset(dis,0,sizeof(dis));
	dfs(1);
	for(int i=1; i<=n; i++)
		if(dis[i]>dis[pos]) pos=i;
	memset(dis,0,sizeof(dis));
	dfs(pos);
 pos=1;
	for(int i=1; i<=n; i++)
		if(dis[i]>dis[pos]) pos=i;
	return dis[pos];
}

    2.树的重心:其所有子树中最大子树的节点数最少,该点是树的重心

      $dfs$求出所有点的子树节点个数,若满足:

      该点的子树的节点数的二倍不小于总点数

      且该点的儿子都满足子树节点数的二倍不超过总点数,这个点就是树的重心。

      注意,树的重心不唯一

void dfs(int now) {
	size[now]=1;
	for(int i=head[now]; i; i=e[i].next)
		int to=e[i].to;
		if(pre[now]!=to) {
			pre[to]=x;
			dfs(to);
			size[now]+=size[to];
		}
	if(size[now]*2>=n&&!ans) ans=now;
}
//ans即为找到的一个重心

   3.最小公共祖先(LCA):

    rmq+dfs序

    tarjan+并查集

    doubly树上倍增(在线算法)

struct node {
	int to,cost,next;
} e[maxm];
int head[maxn],nume;
void add(int a,int b,int c=1) {
	e[++nume]=(node) {b,c,head[a]};
	head[a]=nume;
}
int dt[18][maxn],dis[maxn],dep[maxn];
int cnt;
void ldfs(int now){
	for(int i=head[now];i;i=e[i].next){
		int to=e[i].to;
		if(to!=dt[0][now]){
			dep[to]=dep[now]+1;
			dt[0][to]=now;
			dis[to]=dis[now]+e[i].cost;
			ldfs(to);
		}
	}
}
int lca(int a,int b){
	if(dep[a]>dep[b]) swap(a,b);
	for(int i=17;i>=0;i--){
		if(dep[dt[i][b]]>=dep[a]) b=dt[i][b];
	}
	if(a==b) return a;
	for(int i=16;i>=0;i--){
		if(dt[i][a]!=dt[i][b]){
			a=dt[i][a];
			b=dt[i][b];
		}
	}
	return dt[0][a];
}
void lcainit(){
	dep[1]=dt[0][1]=1;
	ldfs(1);
	for(int i=1;i<=17;i++)
	for(int j=1;j<=n;j++)
		dt[i][j]=dt[i-1][dt[i-1][j]];
}

   生成树:一个子图,使得原图连通且是一棵树

    1.最小生成树:

      kruskal算法:复杂度$O(Elog(E)+Eα(E))$

      prim算法:复杂度$O(Elog(E))$

    2.次小生成树:kruskal算法:$O(mlogm+n*n)$

    3.单点度限制最小生成树:IOI2004国家集训队论文--王汀《最小生成树问题的扩展》,模板

    4.生成树计数:拉普拉斯矩阵,基尔霍夫矩阵树定理

    5.最优比例生成树:Dinkelbach算法

    6.有向图最小生成树:最小树形图,朱刘算法

   平面图:上任意两边不交叉的图,满足欧拉公式:点数+面数=边数+2,且染色色数小于等于4,连通无重边的平面图存在一点度数一定小于等于5

    1.带权平面图的最大流:等价于其对偶图的最短路

    网络流:定义略,S为源点,T为汇点,X为二分图的一边,Y为二分图/拆点的另一边

     1.最大流/最小割:Dinic,ISAP,HLPP,Stoer-Wagner(无向图最小割)

     2.最小费用最大流:SPFA,ZKW「网络流 24 题」运输问题

     3.点流量限制:拆点费用流,洛谷p1006

     4.点/边收益唯一:拆点/加边费用流 「网络流 24 题」深海机器人问题

     5.二分图最大匹配:最大流「网络流 24 题」试题库

     6.二分图最优匹配:费用流 HDU1533

     7.上下界/无源汇/最小可行流:Menci的总结

     8.二分图最大(带权)独立集/最小点权覆盖:

       「网络流 24 题」骑士共存问题 「网络流 24 题」方格取数

       $S$向$X$连容量为权值的边,$Y$向$T$连容量为权值的边。$X$与相连的$Y$连$INF$。

       最大独立集=点权总和-最小割,最小点权覆盖=最小割

     9.二分图最小边覆盖:

      $S$向$X$连容量为权值的边,$Y$向$T$连容量为权值的边。$X$与相连的$Y$连$1$

       最小边覆盖=点数-最大流

     10.DAG最小路径覆盖:「网络流 24 题」魔术球

      拆点,$S$向$X$连容量为1的边,$X_2$向$T$连容量为1的边。对每条边X→Y由$X$向$Y_2$ 连一条容量为1的边。

       最小路径覆盖=点数-最大流

     11.最大权闭合子图:

      $S$连接正权点,$T$连接负权点,取余原图所有边权值$INF$,

        最大权值=正权点之和-最小割,参考集训队论文

     12.分配问题:

      「网络流 24 题」分配问题 「网络流 24 题」负载 HDU4292

      利用流入,流出,容量和费用去满足限制关系

     13.动态流动问题:

       「网络流 24 题」星际转移 对时间进行枚举,构造分层网络等等

     14.最大密度子图:转化为最大权闭合子图推导

       UVa 7037,2014西安区域赛

     15.(最大权)不相交路径问题:限制流入流量

       「网络流 24 题」数字梯形,「网络流 24 题」最长 k 可重区间集

       「网络流 24 题」航空路线问题,「网络流 24 题」最长递增子序列,

      16.限制问题: 难度很大,一般考虑利用枚举,二分,单调性,数学性质等元素进行求解

      Coding Contest

黑人问号???:

    图同构                     

    树同构      

    三元环      

    弦图               

    完美图/伴完美图  

    完美消除序列   

    区间图      

    树分解      

    团树        

    PQ树        

    灭绝树        

    斯坦纳树      

    仙人掌图      

 

posted @ 2018-06-08 16:23  nervending  阅读(1731)  评论(0编辑  收藏  举报