CCF地铁修建(有思路的简介,但是代码分数只有45)

时间:2021-09-19 21:31:54

嗯。。。我用了两个方法一个kruskal,一个prim,前者,运行超时,20分,不知道怎么优化了。难道还要让我在快排的时候,用插入排序优化吗?后一个嗯。。运行错误45分。。也不知道为什么。。我查到的答案都是只有代码,没有思路,那我就来简述下思路吧。就是,最小生成树的思想,一直选择最小的边进入树中,保证天数能够最小。算法中每次循环里面都要更新天数,遇到大的就更新。然后在,最后一个结点进入树中的时候,就跳出算法。如果是kruskal算法,就是第一个结点的树根和最后一个结点的树根相同就退出,如果是prim算法,就是在最后一个结点Visite[最后一个结点] == true 时退出。大概是这样吧。最后新年快乐。我把两段代码贴出来,如果有人能告诉我怎么做就好了。

1.Prim

#include <stdio.h>
#include <malloc.h>

#define true 1
#define false 0
#define INFINITY 1000000
#define MaxVertexNum 100000
#define MaxArcNum 200000

int Visite[MaxVertexNum];
struct ArcStruct {
    int v1, v2, dist;
};
struct GraphStruct {//创建一个最简单的无向图
    int vexnum, arcnum;
    int dist[MaxArcNum];
};
struct MinHeapStruct {
    int size;
    struct ArcStruct a[MaxArcNum];
};
typedef struct GraphStruct* Graph;
typedef struct MinHeapStruct* MinHeap;
typedef struct ArcStruct* Edge;

Graph createGraph();
void initializeGraph( Graph G );
int prim( Graph G, int u );
void swap( int *p1, int *p2 );
int computeNum( int a );
void assignEdge( Edge e, int v1, int v2, int dist );
Edge deleteMinHeap( MinHeap h );

void insertMinHeap( MinHeap h, Edge e );
void swapHeapNode ( Edge e1, Edge e2 );
void assignHeapNode( Edge e1, Edge e2 );

int main( void ) {

    Graph G = createGraph();
    int i = 0;
    int V1, V2;
    int dist;
    int num = 0;
    int mindist = 0;
    for( i = 0; i < G->arcnum; i++ ) {
        scanf("%d %d %d", &V1, &V2, &dist);
        if( V1 < V2 ) {
            swap( &V1, &V2 );
        }
        num = computeNum( V1-1 ) + V2-1;
        G->dist[num] = dist;
    }

    mindist = prim( G, 0 );

    printf("%d", mindist);

    return 0;
}

Graph createGraph() {
    Graph G = ( Graph )malloc( sizeof( struct GraphStruct ) );
    initializeGraph( G );
    return G;
}
void initializeGraph( Graph G ) {
    int i = 0;
    int n = 0;
    scanf("%d %d", &G->vexnum, &G->arcnum);
    n = computeNum( G->vexnum );
    for( i = 0; i < n; i++ ) {
        G->dist[i] = INFINITY;
    }
    for( i = 0; i < G->vexnum; i++ ) {
        Visite[i] = false;//好像这里也可以提出来一个函数
    }

}
int prim( Graph G, int u ) {
    MinHeap h = ( MinHeap )malloc( sizeof(struct MinHeapStruct) );
    h->size = 0;
    h->a[0].dist = -INFINITY;
    Visite[u] = true;
    int mindist = -1;
    Edge e = ( Edge )malloc( sizeof(struct ArcStruct) );

    //make all edges of u into h
    int num, i;
    num = computeNum( u );
    for( i = 0; i < u; i++ ) {
        if( G->dist[num] != INFINITY ) {
            assignEdge( e, u, i, G->dist[num] );
            insertMinHeap( h, e );
        }
        num++;
    }
    for( i = u+1; i < G->vexnum; i++ ) {
        num = computeNum( i ) + u;
        if( G->dist[num] != INFINITY ) {
            assignEdge( e, u, i, G->dist[num] );
            insertMinHeap( h, e );
        }
    }
    //next: MinHeap brings minest dist out, until empty.
    while( h->size != 0 ) {// deleteHeap only  returns one element, so union what need
        e = deleteMinHeap( h );
        if( !Visite[e->v2] ) {
            //make all edges of e->v2 into h
            u = e->v2;
            Visite[u] = true;
            if( mindist < e->dist ) { mindist = e->dist; }
            if( Visite[G->vexnum-1] ) { break; }
            num = computeNum( u );
            for( i = 0; i < u; i++ ) {
                if( G->dist[num] != INFINITY && !Visite[i] ) {
                    assignEdge( e, u, i, G->dist[num] );
                    insertMinHeap( h, e );
                }
                num++;
            }
            for( i = u+1; i < G->vexnum; i++ ) {
                num = computeNum( i ) + u;
                if( G->dist[num] != INFINITY && !Visite[i] ) {
                    assignEdge( e, u, i, G->dist[num] );
                    insertMinHeap( h, e );
                }
            }
        }
    }

    return mindist;
}
void assignEdge( Edge e, int v1, int v2, int dist ) {
    e->v1 = v1;
    e->v2 = v2;
    e->dist = dist;
}
void insertMinHeap( MinHeap h, Edge e ) {
    if( h->size == 0 ) {
        assignHeapNode( &(h->a[++h->size]), e );
        return;
    }
    h->size++;
    int parent, child = h->size;
    assignHeapNode( &(h->a[child]), e );

    for( parent = h->size/2; parent >= 1; parent = child/2 ) {
        if( h->a[parent].dist <= h->a[child].dist ) { break; }
        swapHeapNode( &h->a[parent], &h->a[child] );
        child = parent;
    }
}
Edge deleteMinHeap( MinHeap h ) {
    Edge e = ( Edge )malloc( sizeof(struct ArcStruct) );
    assignHeapNode( e, &(h->a[1]) );
    assignHeapNode( &(h->a[1]), &(h->a[h->size]) );
    h->size--;
    int parent, child;

    for( parent = 1; parent*2 <= h->size; parent = child ) {
        child = parent*2;
        if( child < h->size && (h->a[child+1].dist < h->a[child].dist) ) { child++; }
        if( h->a[parent].dist <= h->a[child].dist ) { break; }
        swapHeapNode( &(h->a[parent]), &(h->a[child]) );
    }

    return e;
}
void assignHeapNode( Edge e1, Edge e2 ) {
    e1->dist = e2->dist;
    e1->v1 = e2->v1;
    e1->v2 = e2->v2;
}
void swapHeapNode ( Edge e1, Edge e2 ) {
    Edge e3 = ( Edge )malloc( sizeof( struct ArcStruct) );
    assignHeapNode( e3, e2 );
    assignHeapNode( e2, e1 );
    assignHeapNode( e1, e3 );
}
int computeNum( int a ) {
    return a*(a-1)/2;
}
void swap( int *p1, int *p2 ) {
    int tmp = 0;
    tmp = *p2;
    *p2 = *p1;
    *p1 = tmp;
}

2.Kruskal

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define MaxArcNum 20000
#define MaxVerNum 10000


struct ArcNode {
    int v1, v2, dist;
};
struct GraphStruct {
    int arcnum, vexnum;
    struct ArcNode a[MaxArcNum];
};
typedef struct GraphStruct* Graph;

int Parent[MaxVerNum];
int Deep[MaxVerNum];

int Kruskal( Graph G );
int findPar( int v );
void uniteTree( int v1, int v2 );
void QuickSort( struct ArcNode a[], int s, int f );
int Partition( struct ArcNode a[], int s, int f );
void swap( struct ArcNode* a, struct ArcNode* b );
int RandPartition( struct ArcNode a[], int s, int f );

void text_QuickSort( struct ArcNode a[], int s, int f );

int main( void ) {

    int i = 0, v1, v2, dist;
    int MinDistTree = 0;
    Graph G = ( Graph )malloc( sizeof(struct GraphStruct) );
    scanf("%d %d", &G->vexnum, &G->arcnum);

    for( i = 0; i < G->arcnum; i++ ) {
        scanf("%d %d %d", &v1, &v2, &dist);

        G->a[i].v1 = v1-1;
        G->a[i].v2 = v2-1;
        G->a[i].dist = dist;
    }

    MinDistTree = Kruskal( G );

    printf("%d", MinDistTree);

    return 0;
}
int Kruskal( Graph G ) {
    int v1, v2, dist = -1, nEdge = 0;
    int i = 0;
    QuickSort( G->a, 0, G->arcnum-1 );//No Problem

    for( i = 0; i < G->vexnum; i++ ) {
        Parent[i] = i;
        Deep[i] = 0;
    }

    for( i = 0; i < G->arcnum && nEdge < (G->vexnum)-1; i++ ) {
        v1 = G->a[i].v1;
        v2 = G->a[i].v2;

        if( findPar(v1) != findPar(v2) ) {
            uniteTree( v1, v2 );
            if( G->a[i].dist > dist ) { dist = G->a[i].dist; }
            nEdge++;
            if( findPar( G->vexnum-1 ) == findPar( 0 ) ) {
                break;
            }
        }
    }

    return dist;
}
int findPar( int v ) {
    int p = Parent[v];
    int lastP = v;

    while( p != lastP ) {
        lastP = p;
        p = Parent[lastP];
    }
    Parent[v] = p;

    return p;
}
void uniteTree( int v1, int v2 ) {
    v1 = findPar( v1 );
    v2 = findPar( v2 );

    if( Deep[v1] < Deep[v2] ) {
        Parent[v2] = v1;
    }
    else {
        Parent[v1] = v2;
        if( Deep[v1] < Deep[v2] ) { Deep[v2]++; }
    }
}
void QuickSort( struct ArcNode a[], int s, int f ) {

    if( s >= f ) { return; }

    int m = 0;
    while( f > s ) {
        m = RandPartition( a, s, f );
        QuickSort( a, s, m-1 );
        s++;
    }
}
int Partition( struct ArcNode a[], int s, int f ) {
    int x = a[f].dist;
    int i = s-1;
    int j = s;

    for( j = s; j <= f-1; j++ ) {
        if( a[j].dist < x ) {
            i++;
            swap( &a[i], &a[j] );
        }
    }
    i = i+1;
    swap( &a[i], &a[f] );
    return i;
}
void swap( struct ArcNode* a, struct ArcNode* b ) {
    struct ArcNode c = *b;
    (*b).dist = (*a).dist;
    (*b).v1 = (*a).v1;
    (*b).v2 = (*a).v2;
    (*a).dist = c.dist;
    (*a).v1 = c.v1;
    (*a).v2 = c.v2;

}
int RandPartition( struct ArcNode a[], int s, int f ) {
    int tmp = rand()%( f-s ) + s;
    swap( &a[tmp], &a[f] );
    return Partition( a, s, f );
}