#include <stdio.h>
#define MAX_MEMBERS 2001
int numOfMembers;
typedef struct Member{
int member;
int next;
}Member;
Member MemberArray[MAX_MEMBERS * MAX_MEMBERS];//用作邻接链表,注意数组别开小了
int MemberNum;
int MemberLastAdded[MAX_MEMBERS];
int clock;
int rootTime[MAX_MEMBERS];
int memberTime[MAX_MEMBERS];
int stack[MAX_MEMBERS];
int top;
int isInStack[MAX_MEMBERS];
int SCCNumArray[MAX_MEMBERS];//strong connected component number array
int numOfSCCs;//number of strong connected components
int visited[MAX_MEMBERS];
int inDegree[MAX_MEMBERS];
void getSCCsByTarjan(int member){
clock++;
rootTime[member] = memberTime[member] = clock;
top++;
stack[top] = member;
isInStack[member] = 1;
int MemberIndex;
for (MemberIndex = MemberLastAdded[member]; MemberIndex != 0; MemberIndex = MemberArray[MemberIndex].next){
int adjaMember = MemberArray[MemberIndex].member;
if (memberTime[adjaMember] == 0){
getSCCsByTarjan(adjaMember);
if (rootTime[adjaMember] < rootTime[member])
//member的孩子adjaMember可以到达祖先rootTime[adjaMember],member也可以到达
rootTime[member] = rootTime[adjaMember];
} else if (isInStack[adjaMember] == 1 && memberTime[adjaMember] < rootTime[member])
//member能到达祖先adjaMember,跟新rootTime[member],这里“祖先”,表面上看是孩子,其实是某个祖先结点
rootTime[member] = memberTime[adjaMember];
}
if (memberTime[member] == rootTime[member]){
//以member为顶点的子树中没有后向边
numOfSCCs++;
int memberPoped;
do {
memberPoped = stack[top];
top--;
isInStack[memberPoped] = 0;
//缩点
SCCNumArray[memberPoped] = numOfSCCs;
} while (memberPoped != member);
}
}
int main(){
scanf("%d", &numOfMembers);
int member;
for (member = 1; member <= numOfMembers; member++){
int adjaMember;
while (scanf("%d", &adjaMember) != EOF && adjaMember != 0){
MemberNum++;
MemberArray[MemberNum].member = adjaMember;
MemberArray[MemberNum].next = MemberLastAdded[member];
MemberLastAdded[member] = MemberNum;
}
}
for (member = 1; member <= numOfMembers; member++)
if (memberTime[member] == 0)
getSCCsByTarjan(member);
//求缩点的入度
for (member = 1; member <= numOfMembers; member++){
int SCCNumOfFrom = SCCNumArray[member];
int MemberIndex;
for (MemberIndex = MemberLastAdded[member]; MemberIndex != 0; MemberIndex = MemberArray[MemberIndex].next){
int adjaMember = MemberArray[MemberIndex].member;
int SCCNumOfTo = SCCNumArray[adjaMember];
if (SCCNumOfFrom != SCCNumOfTo)
inDegree[ SCCNumOfTo ]++;
}
}
//判断入度为0的缩点,即source的个数
int source = 0;
int SCCNumOfSource = 0;
int SCCNum;
for (SCCNum = 1; SCCNum <= numOfSCCs; SCCNum++)
if (inDegree[SCCNum] == 0){
if (++source > 1)
break;
SCCNumOfSource = SCCNum;
}
if (source == 1)
for (member = 1; member <= numOfMembers; member++)
if (SCCNumArray[member] == SCCNumOfSource)
printf("%d ", member);
printf("0\n");
return 0;
}
URAL 1198 Jobbery (强连通分量 Tarjan)
最新推荐文章于 2015-12-01 17:29:00 发布