URAL 1198 Jobbery (强连通分量 Gabow)

#include <stdio.h>
#define MAX_MEMBERS 2000
int numOfMembers;
typedef struct To{
	int member;
	int nextToNum;
}To;
To ToArray[MAX_MEMBERS * MAX_MEMBERS + 1];
int ToNum;
int ToNumLastAdded[MAX_MEMBERS + 1];
int clock;
int pre[MAX_MEMBERS + 1];
int stack1[MAX_MEMBERS + 1];
int top1;
int stack2[MAX_MEMBERS + 1];
int top2;
int SCCNumArray[MAX_MEMBERS + 1];
int numOfSCCs;
int inDegree[MAX_MEMBERS + 1];

void getSCCsByGabow(int from){
	clock++;
	pre[from] = clock;
	top1++;
	stack1[top1] = from;
	top2++;
	stack2[top2] = from;
	int ToNum;
	for (ToNum = ToNumLastAdded[from]; ToNum != 0; ToNum = ToArray[ToNum].nextToNum){
		int to = ToArray[ToNum].member;
		if (pre[to] == 0)
			getSCCsByGabow(to);
		else if (SCCNumArray[to] == 0){
			int minPre = pre[to];
			while (pre[ stack2[top2] ] > minPre)
				top2--;
		}
	}
	if (stack2[top2] == from){
		top2--;
		numOfSCCs++;
		do 
			SCCNumArray[ stack1[top1] ] = numOfSCCs;
		while (stack1[top1--] != from);
	}
}

int main(){

	scanf("%d", &numOfMembers);
	int from, to;
	for (from = 1; from <= numOfMembers; from++)
		while (scanf("%d", &to) != EOF && to != 0){
			ToNum++;
			ToArray[ToNum].member = to;
			ToArray[ToNum].nextToNum = ToNumLastAdded[from];
			ToNumLastAdded[from] = ToNum;
		}
	
	for (from = 1; from <= numOfMembers; from++)
		if (pre[from] == 0)
			getSCCsByGabow(from);

	for (from = 1; from <= numOfMembers; from++){
		int ToNum;
		for (ToNum = ToNumLastAdded[from]; ToNum != 0; ToNum = ToArray[ToNum].nextToNum){
			int to = ToArray[ToNum].member;
			if (SCCNumArray[from] != SCCNumArray[to])
				inDegree[ SCCNumArray[to] ]++;
		}
	}

	int source = 0;  
    int SCCNumOfSource = 0;  
    int SCCNum;  
    for (SCCNum = 1; SCCNum <= numOfSCCs; SCCNum++)  
        if (inDegree[SCCNum] == 0){  
            if (++source > 1)  
                break;  
            SCCNumOfSource = SCCNum;  
              
        }  
  
	int member;
    if (source == 1)  
        for (member = 1; member <= numOfMembers; member++)  
            if (SCCNumArray[member] == SCCNumOfSource)  
                printf("%d ", member);  
    printf("0\n");  
  
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值