pku 2263利用kruskal的过程+hash+二分

View Code
/*

  Name: 利用kruskal的过程+hash+二分 

  Copyright: (处理字符串我写复杂了!)

  Author: Try86

  Date: 18/04/12 20:26

  Description: 求连接两点的路径上的最小边权的最大值 

*/





#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <iostream>



using namespace std;



const int L = 35;

const int S = 331;//hash表大小 

const int N = 205;

const int M = 20000;



int sumVs, start, end, p[N]; 

char names[2][M][L], str[N][L], name1[L], name2[L];

struct edge {

    int u;

    int v;

    int w;

}e[M];

struct node {//hash表数据结构相关信息 

    char str[L];

    node *next;

    node(char *ch, node *p) {

        strcpy(str, ch);

        next = p; 

    }

};

struct hash {

    node *link;

}hashTable[S];



int cmp(const void *a, const void *b) {

    return strcmp((char *)a, (char *)b);

}



void init() {

    for (int i=0; i<S; ++i) hashTable[i].link = NULL;

    return ;

}



unsigned int BKDRHash(char *str) {

    unsigned int seed = 131;

    unsigned int hash = 0;

    while (*str) hash = hash * seed + (*str++);

    return hash & 0x7FFFFFFF;

}



void insertAndFind(char *strName) {//字符串判重 

    int k = BKDRHash(strName) % S;

    node *p = hashTable[k].link;

    while (p) {

        if (!strcmp(p->str, strName)) return ;

        p = p->next; 

    }

    node *q = new node(strName, hashTable[k].link);

    hashTable[k].link = q;

    strcpy(str[sumVs++], strName);

    return ;

}



/*

void del(node *p) {

    if (!p) return ;

    del(p->next);

    delete p;

    return ;

}*/



int binarySearch(char *name, int n) {//二分查找字符串所在位置 

    int left = 0;

    int right = n;

    while (left <= right) {

        int mid = (left + right) / 2;

        if (!strcmp(str[mid], name)) return mid;

        if (strcmp(str[mid], name) > 0) right = mid - 1;

        else left = mid + 1; 

    }

}



void initS(int n) {

    for (int i=1; i<=n; ++i) p[i] = i;

    return ;

}



int find(int v) {

    if (p[v] != v) p[v] = find(p[v]);

    return p[v];

}



void join(edge e) {

    int x = find(e.u);

    int y = find(e.v);

    if (x != y) p[x] = y;

    return ;

}



int cmp1(const void *a, const void *b) {

    return ((edge *)b)->w - ((edge *)a)->w;

}



int kruskal(int n, int m) {

    initS(n);

    qsort(e, m, sizeof(edge), cmp1);

    for (int i=0; i<m; ++i) {

        join(e[i]);

        if (find(start) == find(end)) {//起点跟终点在同一个集合时,加入集合的最后一条边权既是所求的答案 

            return e[i].w;

        }

    }    

}



int main() {

    int n, m, t = 0;

    while (scanf("%d%d", &n, &m), n+m) {

        init();

        sumVs = 0;

        for (int i=0; i<m; ++i) {//输入数据,并判重 

            scanf ("%s%s%d", names[0][i], names[1][i], &e[i].w);

            insertAndFind(names[0][i]);

            insertAndFind(names[1][i]);

        }

        scanf ("%s%s", name1, name2);

        qsort(str, sumVs, sizeof(str[0]), cmp);

        for (int i=0; i<m; ++i) {//建图 

            int u = binarySearch(names[0][i], n) + 1;

            int v = binarySearch(names[1][i], n) + 1;

            e[i].u = u, e[i].v = v;

        }

        start = binarySearch(name1, n) + 1;//起点位置 

        end = binarySearch(name2, n) + 1;//终点位置 

        int ans = kruskal(n, m);

        printf ("Scenario #%d\n%d tons\n\n", ++t, ans);

//        for (int i=0; i<S; ++i) del(hashTable[i].link);

        for (int i=0; i<S; ++i) {

            node *p = hashTable[i].link;

            while (p) {

                hashTable[i].link = p->next;

                delete p;

                p = hashTable[i].link;

            }

        }

    }

    return 0;

}

 

你可能感兴趣的:(hash)