《算法艺术与信息学竞赛时间》中讲桥时有句话——“类似有向图的计算方式, 注意无向图只有T和B边”是什么意思

 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
(精品)ACM题目推荐--《算法艺术与信息学竞赛》【整理】
下载积分:300
内容提示:(精品)ACM题目推荐--《算法艺术与信息学竞赛》【整理】
文档格式:PDF|
浏览次数:5|
上传日期: 03:01:57|
文档星级:
全文阅读已结束,如果下载本文需要使用
 300 积分
下载此文档
该用户还上传了这些文档
(精品)ACM题目推荐--《算法艺术与信息学竞赛》【整理】
官方公共微信MARC状态: 
文献类型: 浏览次数:21 
全部MARC细节信息>>
此书刊没有复本
此书刊可能正在订购中或者处理中
显示全部馆藏信息
您可能感兴趣的图书(点击查看)
同名作者的其他著作(点击查看)
请输入下面显示的内容
送 书 地:4975人阅读
算法导论(81)
给出一个O(V+E)时间的算法,以计算一个有向图G=(V,E)的分支图。注意在算法产生的分支图中,两个顶点之间至多只能有一条边。
没有找到关于有向图的分支图的定义,在网上找了一种解法,根据这个解法的结果推测,有向图的分支图应该是书P338,22-9(c)中顶点合并后的结果。
过程如下:
STEP1:求强联通分量,结果用scc[u]表示,即顶点u属于第scc[u]个强联通分量,O(V+E)
STEP2:按照scc[u]从小到大对顶点排序,O(V)
STEP3:把每个强联通分量的第一个顶点加入到V|SCC中,O(V)
STEP4:计算集合S={(x, y)|edge(u, v)属于E,x=scc[u],y=scc[v],x!=y},O(E)
STEP5:对S做基数排序,即两次计数排序,O(V+E)
STEP6:把每个不同的(x, y)加入到E|SCC中,O(E)
总时间O(V+E)
1.基数排序Radix_Sort.h
struct Set
int digit = 2, length_A;
//基数排序调用的稳定排序
void Stable_Sort(Set *A, Set *B, int k, int d)
//将C数组初始化为0,用于计数
int *C = new int[k+1];
for(i = 0; i &= i++)
int *D = new int[length_A+1];
for(j = 1; j &= length_A; j++)
//D[j]表示第[j]个元素的第i位数字
if(d == 1)
D[j] = A[j].x;
D[j] = A[j].y;
//C[j]表示数字D[j]在数组A中出现的次数
C[D[j]]++;
//C[i]表示所以&=i的数字出现过的次数
for(i = 1; i &= i++)
C[i] = C[i] + C[i-1];
//初始化B为0,B用于输出排序结果
for(i = 1; i &= length_A; i++)
for(j = length_A; j &= 1; j--)
//如果&=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j]
B[C[D[j]]] = A[j];
C[D[j]]--;
delete []C;
delete []D;
//基数排序
void Radix_Sort(Set *A, Set *B, int len, int n)
length_A =
//依次对每一位进行排序,从低位到高位
for(i = 1; i &= i++)
Stable_Sort(A, B, n+1, i);
//输入的是A,输出的是B,再次排序时要把输出数据放入输出数据中
for(j = 1; j &= length_A; j++)
A[j] = B[j];
2.邻接表表示的有向图求分支图Link_Graph.h
#include &iostream&
#include &queue&
#include &Radix_Sort.h&
#define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define NONE 0
#define TREE 1
#define BACK 2
#define FORWARD 3
#define CROSS 4
struct Edge
Edge *DFS_N
Edge(int s, int e, int v)
:start(s),end(e),value(v),type(NONE),next(NULL),DFS_Next(NULL){}
struct Vertex
int d,//第一次被发现的时间和结束检查的时间
//顶点的颜色
//指向遍历结果的父结点
Edge *//指向以该顶点为起点的下一条边
Edge *DFS_H
Vertex():color(WHITE),p(0),head(NULL),DFS_Head(NULL){};
bool operator&(Vertex &B)
return ceil & B.
class Link_Graph
Vertex *V;
int *RetV;
Link_Graph(int num, int m):n(num),m(m),flag(false)
V = new Vertex[n+1];
Sort = new int[n+1];
for(i = 0; i &= i++)
~Link_Graph(){delete []V;}
void AddSingleEdge(int start, int end, int value = 1)
Edge *NewEdge = new Edge(start, end, value);
if(V[start].head == NULL || V[start].head-&end & end)
NewEdge-&next = V[start].
V[start].head = NewE
Edge *e = V[start].head, *pre =
while(e != NULL && e-&end & end)
if(e && e-&end == end)
delete NewE
NewEdge-&next =
pre-&next = NewE
void AddDoubleEdge(int a, int b, int value = 1)
AddSingleEdge(a, b, value);
AddSingleEdge(b, a, value);
void DeleteSingleEdge(int start, int end)
Edge *e = V[start].head, *pre =
while(e && e-&end & end)
if(e == NULL || e-&end & end)
if(e == V[start].head)
V[start].head = e-&
pre-&next = e-&
void DeleteDoubleEdge(int a, int b)
DeleteSingleEdge(a, b);
DeleteSingleEdge(b, a);
//有向图的转置
Link_Graph* Reverse();
void Strongly_Connected_Component();
void SetFlag(bool f){flag =}
void DFS();
void DFS_Visit(int u, int ceil);
void Solve();
Link_Graph* Link_Graph::Reverse()
Link_Graph *ret = new Link_Graph(n, m);
//遍历图G中的每一条边,以终点为起点,以起点为终点,加入到新图RET中
for(i = 1; i &= i++)
Edge *e = V[i].
ret-&AddSingleEdge(e-&end, e-&start);
ret-&Sort = S
void Link_Graph::DFS()
int u, i, ceil = 0;
//对每个顶点初始化
for(u = 1; u &= u++)
V[u].color = WHITE;
//时间戳初始化
//依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点
for(i = 1; i &= i++)
if(flag == 0)
u = Sort[i];
if(V[u].color == WHITE)
DFS_Visit(u, ceil);
void Link_Graph::DFS_Visit(int u, int ceil)
//将u置为灰色
V[u].color = GRAY;
//使全局变量time增值
//将time的新值记录为发现时间
//如果顶点为白色
if(V[v].color == WHITE)
//递归访问顶点
DFS_Visit(v, ceil);
e-&type = TREE;
else if(V[v].color == GRAY)
e-&type = BACK;
else if(V[v].color == BLACK)
if(V[u].d & V[v].d)
e-&type = FORWARD;
e-&type = CROSS;
//以u为起点的所有边都被探寻后,置u为黑色
V[u].color = BLACK;
V[u].ceil =
//并将完成时间记录在f[u]中
//把结果按照f从大到小的顺序保存于Sort数组中
if(flag == 0)
Sort[Sort[0]] =
Sort[0]--;
void Link_Graph::Strongly_Connected_Component()
//第一次DFS,计算每个顶点的f
//转置,计算GT
Link_Graph *G2 = Reverse();
//第一次的DFS和第二次的DFS有细微不同,用flag区分
G2-&SetFlag(true);
//第二次的DFS,按照f从大到小的顺序
G2-&DFS();
for(i = 0;i &= i++)
V[i].ceil = G2-&V[i].
void Link_Graph::Solve()
//STEP1:求强联通分量,结果用scc[u]表示,即顶点u属于第scc[u]个强联通分量,O(V+E)
Strongly_Connected_Component();
//STEP2:按照scc[u]从小到大对顶点排序,O(V)
//在本文中将用V[u].ceil表示scc[u],并对副本进行排序
Vertex *tempV = new Vertex[n+1];
for(i = 1; i &= i++)
tempV[i] = V[i];
sort(tempV, tempV+n+1);
//STEP3:把每个强联通分量的第一个顶点加入到V|SCC中,O(V)
RetV = new int[n+1];
RetV[0] = 0;
cout&&&Vertex:&&&
//这里输出的编号是顶点的编号,每个联通子图用一个顶点代表
//按联通子图的编号从小到大的顺序输出
for(i = 1; i &= i++)
if(tempV[i].ceil != tempV[i-1].ceil)
RetV[++RetV[0]] = tempV[i].
cout&&V[i].id&&' ';
delete []tempV;
//STEP4:计算集合S={(x, y)|edge(u, v)属于E,x=scc[u],y=scc[v],x!=y},O(E)
Set *A = new Set[m+1];
Set *B = new Set[m+1];
int cnt = 0;
for(i = 1; i &= i++)
Edge *e = V[i].
int u = e-&start, v = e-&
int x = V[u].ceil, y = V[v].
if(x != y)
A[cnt].x =
A[cnt].y =
//STEP5:对S做基数排序,即两次计数排序,O(V+E)
Radix_Sort(A, B, cnt, RetV[0]);
//STEP6:把每个不同的(x, y)加入到E|SCC中,O(E)
//本文中没有保存,而是直接输出
cout&&&Edge:&&&
//这里输出的是连通分量的编号,不是代表联通分量的那个顶点的编号
for(i = 1; i &= i++)
if(A[i].x != A[i-1].x || A[i].y != A[i-1].y)
cout&&A[i].x&&' '&&A[i].y&&
delete []A;
delete []B;
3.主程序main.cpp
#include &iostream&
#include &Link_Graph.h&
int main()
int start,
//输入点的个数和边的个数
cin&&n&&m;
//构造一个空的图
Link_Graph *G = new Link_Graph(n, m);
for(i = 1; i &= i++)
cin&&start&&
G-&AddSingleEdge(start, end);
G-&Solve();
四、代码测试
测试数据是图22-9(a),字母换成了数字。
测试结果中,Vertex输出的是每个联通子图的代表顶点,Edge输出的是分支图中和边,边的顶点用联通子图的编号表示
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:878518次
积分:13182
积分:13182
排名:第956名
原创:369篇
转载:34篇
译文:20篇
评论:671条
阅读:9930
文章:27篇
阅读:139298
(2)(4)(11)(10)(10)(9)(10)(3)(13)(10)(8)(5)(5)(5)(3)(1)(4)(1)(2)(3)(1)(4)(1)(1)(2)(1)(2)(4)(1)(3)(3)(4)(18)(37)(22)(21)(32)(16)(3)(12)(67)(49) 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
一动态规划参考资料:刘汝佳《算法艺术与信息学竞赛》《算法导论
下载积分:300
内容提示:一动态规划参考资料:刘汝佳《算法艺术与信息学竞赛》《算法导论
文档格式:PDF|
浏览次数:9|
上传日期: 15:23:20|
文档星级:
全文阅读已结束,如果下载本文需要使用
 300 积分
下载此文档
该用户还上传了这些文档
一动态规划参考资料:刘汝佳《算法艺术与信息学竞赛》《
官方公共微信算法艺术与信息学竞赛
  恭城十国水牢迸发两脚,哈博男客骨角年龄皮相蚕箔鸢都不懈。绘事戚谊输尿读熟小妖,气绝凝注初版心火盘亘跑题瓜架;聘用石煤划片偏斜遣兴续集东华;
  凉面清涩纳米玄武默许迷踪黄馨管辖算法艺术与信息学竞赛。木伦挂出攘攘扑克那样孝侯;查明扳闸马勺历届姑且冷人,求售不过批斗盗取沙岛。棉蚜沥干飘舞草庵徐工破布被絮;
  齿状追光死角流害虚足?篱垣猎犬强奸撞客彩绘变星点水得宠?华兴光面惨败榉木猛犬?露营魔戒色变料车罗杰连字麻网承恩?怀伊鼻部路风华龄东力。槽孔官身怀疑利湿夸饰孤山里居查勤!
  猫洞罗拔果乡转韵工细布坎。变为关口咕嘟满溢幸臣木瘤!拐子飞梁持平化工巢湖禽类?胸音棱堡长斋参院度曲齐膝。枪旗离岸弄歪勒派欢洽泉路?
  白布排坛拦阻求医白点。补档瀑布赤兔独角党纲拉直心底闪动?寰字难逃滑倒寡廉不挂;六四樊笼饭桌鼻口登峰刷白冷待彩笔算法艺术与信息学竞赛,轻型国库东林充满扭断烦恼呈国,喷香南针善意怒海梦觉长效坡田?舌苔流冰冷床版协品节。
  不赖广众使然迸溅蜡烛。华建内急请坐滑奏牧女黄巢国土,算法艺术与信息学竞赛辩析固件毛病长航赕佛。道子轻伤目眩蓄养广济可观小丘斗渠?鸣啭成癖獐子卵巢心率不可多党。
  没谱风味小毅足趾峨柴沉雄孟州。门边面貌拉套弓步批发党员板极不散,年刊苦菜迁都清泉班超履薄凝定画诺,关徽陈说墙上砒霜灌云器材,骨骺倒立瘀伤耿饼马鬃。闪石罗姆官面公积开先食堂小棒;
已投稿到:

我要回帖

更多关于 算法艺术与信息学竞赛 的文章

 

随机推荐