http://acm.pku.edu.cn/JudgeOnline/problem?id=2263 hash + dijkstra 第一次用hash,据说某某学长在面试的时候写了个楼天成的hash函数,面试官二话不说,直接拉人~~ #include <cstdlib> #include <iostream> using namespace std; const int N =202; const int inf = 0x3fffffff; //一个比较大的质数,数组只开了202,而hash地址开到了99991。。。~~ const int prim = /*99991*/203; int s,t; int a[N][N];//city之间的距离 //所有hash地址为ha的关键字连成一个链表,hash[ha]指向这个链表头结点(或者尾结点) int hash[prim];//hash链接表 int n,r; struct Str { char ch[31]; int next;//记录有冲突的同义词~~ }str[N]; /********************************************** *将一个字符串的数组中的每个元素依次按前四位与上一个元素的低四位相与组成一个长整形, *如果长整的高四位大于零,那么就将它折回再与长整的低四位相异或. *这样最后得到的长整对HASH表长取余,得到在HASH中的位置. **********************************************/ int ELFhash(char *key) { unsigned long h =0; while(*key) { h =(h<<4)+*key++; unsigned long g = h & 0xf0000000; //如果最高的四位不为0,则说明字符多余7个,如果不处理,再加第九个字符时,第一个字符会被移出,因此要有如下处理。 //该处理,如果对于字符串(a-z 或者A-Z)就会仅仅影响5-8位,否则会影响5-31位,因为C语言使用的算数移位.(右移的时候用符号位填充) if(g) h ^= g >>24; //清空28-31位 h &= ~g; } return h % prim; } int count; int GetID(char *u) { //根据字符串获取他的不重复id号 int ha = ELFhash(u); int j = hash[ha]; while(j) { //搜索hash链接表,遍历所有同义词 if(strcmp(str[j].ch,u) ==0) { return j; } j = str[j].next; } //如果没有找到,则重新分配id给u字符串 strcpy(str[count].ch, u); //插入到头结点 //str[count].next= hash[ha]; //hash[ha] = count; //插入到尾结点 str[hash[ha]].next = count; hash[ha] = count; count ++; return count-1; } int GetF(char *key)//根据0-9字符串转换成整形 { int t =0; while(*key) { t *= 10; t += (*key++ - '0'); } return t; } int d[N];//路径中最大路段距离 bool b[N];//记录city是否已被遍历 //贪心加dp数组记录最大值 int Solve()//dijkstra { memset(d,-1,sizeof(d)); memset(b,0,sizeof(b)); d[s] =inf; b[s] = 1; int src =s; for(int i=1;i<n;i++) { //每扩展一个结点就更新一次d[] for(int j =1;j<=n;j++) { if(!b[j] && -1 !=a[src][j]) { //到prev结点的路径的最大段与prev结点到cur结点的的距离,二者中选小的 //再与当前记录的到cur结点的路径中的最大段中选最大的 //以更新d[cur] d[j] =max(d[j],min(d[src],a[src][j])); } } //寻找下一个扩展结点 int p = -1; for(int j =1;j<=n;j++) { if(!b[j] && d[j]> p) { src = j; p = d[j]; } } if(src == t) break; b[src] =1; } return d[t]; } int main(int argc, char *argv[]) { int ct =1; while(scanf("%d %d",&n,&r) && (n || r)) { printf("Scenario #%d/n",ct); char u[31],v[31],f[12]; memset(hash,0,sizeof(hash)); memset(a,-1,sizeof(a)); count =1; for(int i =0;i< r;i++) { scanf("%s %s %s",u,v,f); int uid = GetID(u); int vid = GetID(v); int fr = GetF(f); a[uid][vid] =fr; a[vid][uid] =fr; } scanf("%s %s",u,v); s = GetID(u);//设置起点和终点 t = GetID(v); printf("%d tons/n/n",Solve()); ct ++; } system("PAUSE"); return EXIT_SUCCESS; }