图论

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

POJ 1386 Play on words
• 题目意思: • 给出几个单词,能否找到一个序列,使得第 一个单词的末尾字母是第二个单词的首字母, 第二个单词的末尾字母是第三个单词的首字 母,以此类推 • 如acm->malform->mouse,符合题目要求, 输出“Ordering is possible.”否则输出 “The door cannot be opened.”。
fleury(弗罗莱)算法
栈: 1425627346 选取点: 7 线路: 1
fleury(弗罗莱)算法
栈: 14256273467 选取点: 5 线路: 1
fleury(弗罗莱)算法
栈: 1425627346 选取点: 7 线路: 1 5
fleury(弗罗莱)算法
栈: 142562734 选取点: 6 线路: 1 5 7
fleury(弗罗莱)算法
栈: 1 4 2 5 选取点: 1 线路:
fleury(弗罗莱)算法
栈: 1 4 2 选取点: 5 线路:1
fleury(弗罗莱)算法
栈: 1 4 2 5 选取点: 6 线路: 1
fleury(弗罗莱)算法
栈: 1 4 2 5 6 选取点: 2 线路: 1
fleury(弗罗莱)算法
部分代码:
• void dfs(int t) • { flag[t] = 1; num++; for(int i = 0 ; i < 26; i++){ • if(!flag[i] && map[t][i]) • dfs(i); } • }
求无向图欧拉回路的算法 ——fleury(弗罗莱)算法
• §任取一个起点,开始下面的步骤 • (1)、如果该点没有相连的点,就将该点 加进路径中然后返回。 • (2)、如果该点有相连的点,就列一张相 连点的表然后遍历它们直到该点没有相连 的点。(遍历一个点,删除一个点) • (3)、处理当前的点,删除和这个点相连的 边, 在它相邻的点上重复上面的步骤,把当前 这个点加入路径中.
方法一、二分图匹配
例题2 hdu 2458

http://acm.hdu.edu.cn/showp roblem.php?pid=2458
问题描述

幼儿园里有许多的男孩和女孩,男 孩彼此都认识,女孩也是。然而只 有部分男孩与女孩认识。幼儿园里 做游戏,老师想找尽量多的同学参 加,这个游戏要求参加的人都相互 认识,问:最多能找出多少人?

该你们练了~
二、欧拉路径问题
一笔画问题
• 大家知道一笔画问题吗。即平面上由 曲线段构成的一个图形能不能一笔画 成,使得在每条线段上都不重复?例 如汉字‘日’和‘中’字都可一笔画, 而‘田’和‘目’则不能。
• 数学家欧拉找到一笔画的规律是: • ⒈凡是由偶点组成的连通图,一定可以一 笔画成。画时可以把任一偶点为起点,最 后一定能以这个点为终点画完此图。 • ⒉凡是只有两个奇点的连通图(其余都为 偶点),一定可以一笔画成。画时必须把 一个奇点为起点,另一个奇点终点。 • ⒊其他情况的图都不能一笔画出。(有偶 数个奇点除以二便可算出此图需几笔画 成。)
欧拉回路存在性的判定:
• 一、无向图 • 每个顶点的度数都是偶数,则存在欧拉回 路。 • 二、有向图(所有边都是单向的) • 每个节顶点的入度都等于出度,则存在欧 拉回路。
欧拉路径存在性的判定
• 一、无向图 • 一个无向图存在欧拉路径,当且仅当 该图所 有顶点的度数为偶数 或者 除了两个度数为 奇数外其余的全是偶数。 • 二、有向图 • 一个有向图存在欧拉路径,当且仅当 该图所 有顶点的度数为零 或者 一个顶点的度数为 1,另一个度数为-1,其他顶点的度数为0。
int dfs(int *adj,int total,int cnt){ int i,j,k; int t[maxn]; if (total==0){ if (best<cnt){ best=cnt; return 1; } return 0; } for (i=0;i<total;i++){ if(cnt+(total-i) <= best) return 0; for(k=0,j=i+1;j<total;j++) if(g[adj[i]][adj[j]]) t[k++]=adj[j]; if(dfs(t,k,cnt+1)) return 1; } return 0; }
思路: 男孩?? With 女孩?? —>>>二分图
问题解决
1、二分图的建立 2、求最大匹配 3、求最大团
代码
int main(){ int i,j; int x,y,c=0; while(scanf("%d%d%d",&n,&m,&xx)!=EOF){ if(n==0&&m==0&&xx==0) break; memset(map,0,sizeof(map)); for(i=1;i<=xx;i++){ scanf("%d%d",&x,&y); map[x][y]=1; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) map[i][j]=1-map[i][j]; printf("Case %d: %d\n",++c,n+m-maxmatch()); } }
• 有关一笔画的三条结论,人们通常称 之为欧拉定理。对于一个连通图,通 常把从某结点出发一笔画成所经过的 路线叫做欧拉路。人们又通常把一笔 画成回到出发点的欧拉路叫做欧拉回 路。具有欧拉回路的图叫做欧拉图。
欧拉回路
• 如下图, 每条边经过一次且仅一次的称 为欧拉回路(euler cycle, euler circuit).
fleury(弗罗莱)算法
栈: 14256273 选取点: 4 线路: 1 5 7 6
fleury(弗罗莱)算法
栈: 1425627 选取点: 3 线路: 1 5 7 6 4
fleury(弗罗莱)算法
栈: 142562 选取点: 7 线路源自文库 1 5 7 6 4 3
fleury(弗罗莱)算法
栈: 14256 选取点: 2 线路: 1576437
int sp(int s){ int i; for(i=1;i<=m;i++) if(map[s][i]&&!v[i]){ v[i]=1; if(!pre[i]||sp(pre[i])){ pre[i]=s; return 1; } } return 0; } int maxmatch(){ int i,max; max=0; memset(pre,0,sizeof(pre)); for(i=1;i<=n;i++){ memset(v,0,sizeof(v)); if(sp(i)) max++; } return max; }
fleury(弗罗莱)算法
栈: 选取点: 1 线路: 157643726524
fleury(弗罗莱)算法
栈: 选取点: 线路: 1576437265241
• 具体代码见附件
POJ 2337 Catenyms
• 题目大意: • 与上一题相似,问单词首尾相接,问 是否可以把所有单词串成一串,如果 可以打印出来,要求打印字典序最小 的。
图论选讲
(Rainbow)
一、最大团问题
基本概念



团是指G的一个完全子图,该子图不 包含在任何其他的完全子图当中。最大 团指其中包含顶点最多的团 无向图的最大独立数: 从V个顶点中选出 k个顶,使得这k个顶互不相邻。 那么 最大的k就是这个图的最大独立数. 最大团=补图的最大独立集=V-补图最 大匹配数
方法
• 第一步:建图,以每个单词为边,单词的首尾 字母为点连边,由于题目要求按单词的字典序 输出,所以只记录每个边的起点和终点,不真 正连边 。
• 第二步:判断是否存在欧拉路径,有向图的判 断方法是,最多有1个点的入度比出度小1,最 多有1个点的出度比入度小1,除了这2点外, 其余的点入度和出度必须相等,此外,还要求 图是连通的(其实是边之间是连通的) • 第三步:fleury算法,输出路径。
栈: 1 4 2 5 6 2 选取点: 7 线路: 1
fleury(弗罗莱)算法
栈: 1 4 2 5 6 2 7 选取点: 3 线路: 1
fleury(弗罗莱)算法
栈: 1 4 2 5 6 2 7 3 选取点: 4 线路: 1
fleury(弗罗莱)算法
栈: 1 4 2 5 6 2 7 3 4 选取点: 6 线路: 1
fleury(弗罗莱)算法
栈: 1 4 2 5 选取点: 6 线路: 15764372
fleury(弗罗莱)算法
栈: 1 4 2 选取点: 5 线路: 157643726
fleury(弗罗莱)算法
栈: 1 4 选取点: 2 线路: 1576437265
fleury(弗罗莱)算法
栈: 1 选取点: 4 线路: 15764372652
• 明显,我们可以构造一个图来解决这个 问题。 • 如何转换:一个单词的第一个字母和最 后一个字母作为点,由第一个字母向最 后一个字母连一条有向边。同样,对于 malform,我们就连一条环在m上。 问题转化为判断一个有向图是否存在欧拉 回路或者欧拉路径
• 有向图判断是否存在欧拉回路或欧拉路径 • 首先,要满足其基图(即把边改成无向的图) 是连通的(并查集或者dfs判断) • 然后,判断的时候要注意两种情况: • 1.满足回路的条件是每个定点的入度与出度 相等; • 2.路径的条件是当且仅有一个顶点的入度比 出度大一,和当且仅有一个顶点的出度比入 度大一
方法一、回溯法(暴力)
例题1 hdu 1530

http://acm.hdu.edu.cn/showpro blem.php?pid=1530
题目描述

输入一个邻接矩阵,1代表有 边,要求输出最大团的顶点数
算法分析
部分代码
int clique(){ int i,j,k; int adj[maxn]; //if(n<=0) return 0; best=0; for (i=n-1;i>=0;i--){ for(k=0,j=i+1; j<n; j++) if(g[i][j]) adj[k++] = j; dfs(adj,k,1); } return best; }
fleury(弗罗莱)算法
下图每个节点的度都是偶数,存在欧拉路径
栈: 选取点: 线路:
fleury(弗罗莱)算法
栈: 选取点: 1 线路:
fleury(弗罗莱)算法
栈: 1 选取点: 4 线路:
fleury(弗罗莱)算法
栈:1 4 选取点: 2 线路:
fleury(弗罗莱)算法
栈: 1 4 2 选取点: 5 线路:
吉林大学模板
• /*==============================*\ • | 欧拉路径 O(E) • | INIT: adj[][]置为图的邻接表; cnt[a]为a点 的邻接点个数; • | CALL: elpath(0); 注意:不要有自向边 • \*=============================*/
• • • • • • •
int adj[V][V], idx[V][V], cnt[V], stk[V], top; int path(int v){ for (int w ; cnt[v] > 0; v = w) { stk[ top++ ] = v; w = adj[v][ --cnt[v] ]; adj[w][ idx[w][v] ] = adj[w][ --cnt[w] ]; // 处理的是无向图—-边是双向的,删除v->w后, 还要处理删除w->v • } • return v; • }
最大团解决方法

最大团问题(Maximum Clique Problem, MCP)是图论中一个经典的 组合优化问题,也是一类NP完全问题, 在国际上已有广泛的研究,而国内对 MCP问题的研究则还处于起步阶段, 因此,研究最大团问题具有较高的理 论价值和现实意义。
最大团解决方法

最大团问题又称为最大独立集问题 (Maximum Independent Set Problem)。 目前,求解MCP问题的算法主要分为两类: 确定性算法和启发式算法。确定性算法有 回溯法、分支限界法等,启发式算法蚁群 算法、顺序贪婪算法、DLS-MC算法和智能 搜索算法等。不管哪种算法,都要求在多 项式时间内求得MCP问题的最优解或近似 解。
相关文档
最新文档