woj 1078 并查集 hash
来源:互联网 发布:淘宝商城平板电脑 编辑:程序博客网 时间:2024/06/05 02:22
//方法是把边按权排序(从大到小),然后顺序加进图中。//如果加到某条边时起点和终点连通,那么这条边的权就是要求的宽度#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int M=10001;struct hlb{ unsigned long rate; char s[30]; int p; hlb *next; }*hash[M];struct lb{ int u,v,w; }date[1000010];char sa[30],sb[30];int w,num,n,m;int f[2010],rank[2010];int shash( char *key){ unsigned long h=0; while(*key) { h=(h<<4)+*key++; unsigned long g=h & 0Xf0000000L; if (g) h^=g>>24; h&=~g; } return h;}bool comp(lb a,lb b){ return a.w>b.w;}//宽度由大到小排序int hfind( char *s){ unsigned long k=shash(s); int d=k%M; hlb *pt; pt=hash[d]; while(pt) { if (pt->rate==k&&strcmp(pt->s,s)==0) return pt->p; pt=pt->next; } pt=new hlb; pt->rate=k; pt->p=++num; strcpy(pt->s,s); pt->next=hash[d]; hash[d]=pt; return num;}int ff(int k){ if (k!=f[k])f[k]=ff(f[k]); return f[k];}void uno(int i, int j){ if (ff(i)==ff(j)) return ; if (rank[f[i]]<=rank[f[j]]) { if (rank[f[i]]==rank[f[j]])rank[f[j]]++; f[f[i]]=f[j]; } else f[f[j]]=f[i];}int main(){int i,a,b,start,over;while(scanf("%d%d",&n,&m)==2){if (m>1000000) while(1);memset(hash,0,sizeof(hash));num=0;for(i=1;i<=m;i++){ scanf("%s%s%d",sa,sb,&date[i].w); date[i].u=hfind(sa); date[i].v=hfind(sb); if (num>n||num>2000)while(1);}scanf("%s%s",sa,sb);start=hfind(sa);over=hfind(sb);sort(date+1,date+1+m,comp);for(i=1;i<=n;i++)f[i]=i;memset(rank,0,sizeof(rank));for(i=1;i<=m;i++){ uno(date[i].u,date[i].v); if (ff(start)==ff(over)) { printf("%d\n",date[i].w); break; }}if (i>m)printf("-1\n");}return 0;}
题目最困难的地方就是如何处理地点,大神用的hash我在算法书上看到过,但是自己还是没有掌握呀.