woj 1078 并查集 hash

//方法是把边按权排序(从大到小),然后顺序加进图中。
//如果加到某条边时起点和终点连通,那么这条边的权就是要求的宽度
#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我在算法书上看到过,但是自己还是没有掌握呀.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值