6-10 Strongly Connected Components(30 分)
2018-01-15 14:00
337 查看
为了便于测试也写了ReadG()
自己测试没问题,但目前仍无法通过测试样例
怀疑是结构体指针的分配与题目用意不符,
另外孤立点的输入格式不明
Tarjan算法参考修改自: http://blog.csdn.net/qq_34374664/article/details/77488976#
自己测试没问题,但目前仍无法通过测试样例
怀疑是结构体指针的分配与题目用意不符,
另外孤立点的输入格式不明
Tarjan算法参考修改自: http://blog.csdn.net/qq_34374664/article/details/77488976#
//ReadG()可实现: //1.顶点序号任意(但需唯一) //2.顶点输入顺序任意 //ReadG()未实现: //1.输入顶点的序号的排序//非必要 //2.入度大于零且出度等于零的顶点的确定//二分查找可更快 //ReadG()问题: //1.PtrToVNode *Array 和 PtrToVNode Next 的分配是否合理? /* 本程序的分配方法 基于如下的题目定义: typedef struct VNode *PtrToVNode; struct VNode { Vertex Vert; PtrToVNode Next; }; typedef struct GNode *Graph; struct GNode { int NumOfVertices; int NumOfEdges; PtrToVNode *Array; };//题目定义引用结束 指针分配方法: 1. Graph graph = (Graph)malloc(sizeof(struct GNode)); 2.二级指针 Array 申请连续空间存放 一级指针, graph->Array = (PtrToVNode *)malloc(graph->NumOfVertices * sizeof(PtrToVNode)); 3.每一个一级指针 Array[i]申请连续空间存放 struct VNode 变量 for(i = 0; i < graph->NumOfVertices; ++i) graph->Array[i] = (PtrToVNode)malloc(graph->NumOfVertices * sizeof(struct VNode)); 4.至此生成了 NumOfVertices * NumOfVertices 的 邻接表 */ //2.孤立点(出度为零且入度为零)的输入格式? /* 基于 Sample Input 格式, 本程序方法是输入 5 -2 确认 5 为孤立点 // 孤立点指向一个不可能的输入点(本程序设定为-2) */ //StronglyConnectedComponents函数 使用的是 Tarjan算法 //注意测试用例的最大节点数等于15 超过了 MaxVertices // #include <stdio.h> #include <stdlib.h> //注意测试用例的最大节点数等于15 超过了 MaxVertices #define MaxVertices 10 /* maximum number of vertices */ typedef int Vertex; /* vertices are numbered from 0 to MaxVertices-1 */ typedef struct VNode *PtrToVNode; struct VNode { Vertex Vert; PtrToVNode Next; }; typedef struct GNode *Graph; struct GNode { int NumOfVertices; int NumOfEdges; PtrToVNode *Array; }; Graph ReadG(); /* details omitted */ void PrintV( Vertex V ) { printf("%d ", V); } void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) ); int main() { Graph G = ReadG(); StronglyConnectedComponents( G, PrintV ); return 0; } /* Your function will be put here */ void Insert(int a[], int *size, int x)//仅用于ReadG() { int i, j; for(i = 0; i < (*size); ++i){ if(a[i] == x) return; } ++(*size); a[(*size)-1] = x; } Graph ReadG() { Graph graph = (Graph)malloc(sizeof(struct GNode)); scanf("%d %d", &(graph->NumOfVertices), &(graph->NumOfEdges)); if(graph->NumOfVertices > 15){//15 是测试用例中顶点数最大值 return NULL; } graph->Array = (PtrToVNode *)malloc(graph->NumOfVertices * sizeof(PtrToVNode)); int i; for(i = 0; i < graph->NumOfVertices; ++i) graph->Array[i] = (PtrToVNode)malloc(graph->NumOfVertices * sizeof(struct VNode)); //Essential !!! for(i = 0; i < graph->NumOfVertices; ++i) { graph->Array[i]->Vert = -10;// graph->Array[i]->Next = NULL; } if(graph->NumOfEdges == 0 && graph->NumOfVertices > 0)//只有孤立点,顶点序号从零开始 { for(i = 0; i < graph->NumOfVertices; ++i) { graph->Array[i]->Vert = i; } return graph; } int u, v; PtrToVNode current, //接收当前输入的临时指针,单链表头插法插入graph->Array[j] output; int vert_cnt = 0;//graph->Array[j]->Vert的个数(即起点个数) int j = 0; int *a = (int *)malloc(graph->NumOfVertices * sizeof(int));//存放每条边的终点(a[i]不重复),最后和起点比较得出出度为零且入度大于零的顶点 int len_a = 0;//a中元素个数 for(i = 0; i < graph->NumOfVertices; ++i) a[i] = -8; for(i = 0; i < graph->NumOfEdges; ++i) { scanf("%d %d", &u, &v); if(v == -2){//isolated point graph->Array[i]->Vert = u; graph->Array[i]->Next = NULL;//前面初始化过,不写也行 ++vert_cnt; ++i; continue; } current = (PtrToVNode)malloc(sizeof(struct VNode)); for(j = 0; j < vert_cnt; ++j) { if(u == graph->Array[j]->Vert) { break; } else continue; } if(j == vert_cnt) { graph->Array[j]->Vert = u; ++vert_cnt;//// } current->Vert = v; current->Next = graph->Array[j]->Next; graph->Array[j]->Next = current; Insert(a, &len_a, v); } printf("print a[]\n"); for(i = 0; i < len_a; ++i) { printf("%d ", a[i]); } printf("\nthen initialize the remanent point\n"); //then initialize the remanent point whose outdegree = 0 and indegree > 0 // 存在于a[]且不存在于Array[]的顶点的入度大于零且出度等于零,附加到Array[]后面 int discovered; for(i = 0; i < len_a; ++i) { discovered = 0; for(j = 0; j < vert_cnt; ++j) { if(a[i] == graph->Array[j]->Vert) { discovered = 1; break; } } if(discovered == 0) { graph->Array[vert_cnt]->Vert = a[i]; //graph->Array[j]->Next = NULL; ++vert_cnt; } } printf("Input finished.Then try to output the input.\n"); for(i = 0; i < graph->NumOfVertices; ++i) { PrintV(graph->Array[i]->Vert); output = graph->Array[i]->Next; while(output != NULL) { PrintV(output->Vert); output = output->Next; } if(output == NULL) printf("\n"); } printf("READG() finished.\n"); return graph; } //注意测试用例最大顶点数是 15 ,大于 MaxVertices==10 #define MaxInput 15 Vertex DFN[MaxInput] = {0}, //DFN[]作为这个点搜索的次序编号(时间戳),简单来说就是 第几个被搜索到的。%每个点的时间戳都不一样%。 LOW[MaxInput] = {0}, //作为每个点在这颗树中的,最小的子树的根,每次保证最小,like它的父亲结点的时间戳这种感觉。如果它自己的LOW[]最小,那这个点就应该从新分配,变成这个强连通分量子树的根节点。 //ps:每次找到一个新点,这个点LOW[]=DFN[] stack[MaxInput] = {0}, access[MaxInput] = {0}, cnt = 0, tot = 0, index = 0; int min(int x, int y) { return (x<y)?x:y; } void Tarjan(Graph g, Vertex x, void (*visit)(Vertex V)) { DFN[x] = LOW[x] = ++tot; stack[++index] = x; access[x] = 1; int i; PtrToVNode p; for(i = 0; i < g->NumOfVertices; ++i) { if(g->Array[i]->Vert == x) { for(p = g->Array[i]->Next; p != NULL; p = p->Next) { if(!DFN[p->Vert]){ Tarjan(g, p->Vert, PrintV); 9363 LOW[x] = min(LOW[x], LOW[p->Vert]); } else if(access[p->Vert]){ LOW[x] = min(LOW[x], DFN[p->Vert]); } } break; } } if(LOW[x] == DFN[x]) { do{ PrintV(stack[index]); access[stack[index]] = 0; index--; ++cnt; }while(x != stack[index+1]); if(cnt != g->NumOfVertices) printf("\n"); } } void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) ) { for(int i = 0; i < G->NumOfVertices; ++i) if(DFN[G->Array[i]->Vert]==0) Tarjan(G, G->Array[i]->Vert, PrintV); }
相关文章推荐
- [PTA] week12 4-10 Strongly Connected Components
- POJ 2186 -- Popular Cows (Strongly Connected Components)
- POJ2186 强连通分支(Strongly_Connected_Components)
- Programming Question-4-Strongly Connected Components Problem through DFS
- LeetCode 323. Number of Connected Components in an Undirected Graph(连通分量)
- Codeforces 475 B. Strongly Connected City
- HTML 10-30
- 10-30SQLserver基础--(备份和还原、分离和附加数据库)、语句查询操作
- Strongly connected HDU - 4635(Tarjan+缩点)
- 10 11 30 比较晚
- (30 hackdays day 10) Material design - 可用的Material
- 网络业的 30/10/10 黄金比率
- 7-10 六度空间(30 分)(bfs)
- 分别求1+2+3+...+10,20+21+22+...+30与35+36+37+...+45的和
- 计算1到10 20到30 35到45的和
- [LeetCode] Number of Connected Components in an Undirected Graph 无向图中的连通区域的个数
- 基于 10 大编程语言的 30 个深度学习库
- 练习 求1到10、20到30、35到45的三个和
- 16 - 10 - 30 命令行参数 ----------《c语言程序设计》
- .编写一个Windows应用程序,由给定数据25,15,10,30,20饼图