6-10 Strongly Connected Components(30 分)

为了便于测试也写了ReadG()
自己测试没问题,但目前仍无法通过测试样例
怀疑是结构体指针的分配与题目用意不符,
另外孤立点的输入格式不明
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 
#include 
//注意测试用例的最大节点数等于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 (xNumOfVertices; ++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);
                    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-Data,Structures,and,Algori,图论)