URAL 1198 Jobbery (强连通分量 Tarjan)

来源:互联网 发布:绕过网络白名单限制 编辑:程序博客网 时间:2024/05/20 11:24
#include <stdio.h>#define MAX_MEMBERS 2001int 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 arrayint numOfSCCs;//number of strong connected componentsint 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;}

0 0
原创粉丝点击