![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* 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; }