算法导论 22.5-5 O(V+E)求有向图的分支图

本文详细介绍了如何使用基数排序和邻接表来求解有向图的分支图,通过三个部分——题目阐述、算法思考及代码实现,包括基数排序、图的处理和主程序,展示了完整的O(V+E)复杂度的解决方案,并进行了代码测试验证正确性。
摘要由CSDN通过智能技术生成

一、题目

给出一个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 x;
	int y;
};

int digit = 2, length_A;
//基数排序调用的稳定排序  
void Stable_Sort(Set *A, Set *B, int k, int d)  
{  
    int i, j;  
    //将C数组初始化为0,用于计数  
    int *C = new int[k+1];  
    for(i = 0; i <= k; i++)  
        C[i] = 0;  
    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;
		else
			D[j] = A[j].y;
        //C[j]表示数字D[j]在数组A中出现的次数  
        C[D[j]]++;  
    }  
    //C[i]表示所以<=i的数字出现过的次数  
    for(i = 1; i <= k; i++)  
        C[i] = C[i] + C[i-1];  
    //初始化B为0,B用于输出排序结果  
//    for(i = 1; i <= length_A; i++)  
//        B[i] = 0;  
    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]]--;  
 
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值