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我在算法书上看到过,但是自己还是没有掌握呀.
原创粉丝点击