4298: [ONTAK2015]Bajtocja 启发式合并 hash

来源:互联网 发布:淘宝质量叫高的女装店 编辑:程序博客网 时间:2024/05/17 23:17

好题。好像get了hash的新姿势。我好弱啊。


我们可以用fi,j表示第i个图中点j所属联通块的编号,初始fi,j=j,然后每次连边时,我们可以进行启发式合并,合并的复杂度为O(dnlogn)
如果两个点在所有图中的所属联通块编号都相同,则这两个点是联通的,我们可以hash来判一下,令hashi表示点ihash值,是通过对数组fj,i哈希求出来的(并且为了方便我们支持加减某一位的哈希值)。如果hashi=hashj则证明ij是联通的。我们可以对hash数组再做一次hash,用hashi and U表示hashi的哈希值,U是一个二进制下每位都是1的数,然后在得到的值下面挂一个数组模拟链表就好了。
据CA爷说卡unsigned int。

#include<iostream>#include<cstdio>#define ll unsigned long long #define U 262143#define N 5005#define D 205using namespace std;int fa[D][N],s[D][N],head[D][N],next[D*N*2],list[D*N*2];ll power[D],hash[N],val[N];int head_[U+1],size[N],next_[N],res[N];int n,m,d,cur,ans,cnt;inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void Addedge(int k,int x,int y){    next[++cnt]=head[k][x];    head[k][x]=cnt;    list[cnt]=y;}inline void insert(ll v){    int x=v&U;    for (int i=head_[x];i;i=next_[i])        if (val[i]==v)         {            ans+=2*size[i]+1;            size[i]++;            return;        }    next_[res[cur]]=head_[x]; head_[x]=res[cur]; val[res[cur]]=v; size[res[cur]]=1;    ans++; cur--;}inline void remove(ll v){    int x=v&U;    if (val[head_[x]]==v)    {        ans-=size[head_[x]]*2-1;        if (--size[head_[x]]==0) res[++cur]=head_[x],head_[x]=next_[head_[x]];        return;    }    for (int i=next_[head_[x]],j=head_[x];i;j=i,i=next_[i])        if (val[i]==v)        {            ans-=size[i]*2-1;            if (--size[i]==0) res[++cur]=i,next[j]=next[i];            return;        }}void dfs(int k,int x,int f,int ff){    remove(hash[x]);    hash[x]-=power[k]*fa[k][x];    fa[k][x]=ff;    hash[x]+=power[k]*fa[k][x];    insert(hash[x]);    for (int i=head[k][x];i;i=next[i])        if (list[i]!=f) dfs(k,list[i],x,ff);}inline void unite(int k,int x,int y){    if (fa[k][x]==fa[k][y]) return;    if (s[k][fa[k][x]]>s[k][fa[k][y]]) swap(x,y);    s[k][fa[k][y]]+=s[k][fa[k][x]];     Addedge(k,x,y); Addedge(k,y,x);    dfs(k,x,y,fa[k][y]);}int main(){    d=read(); n=read(); m=read(); power[0]=1;    for (int i=1;i<=d;i++) power[i]=power[i-1]*2333;    for (int i=1;i<=n;i++) res[++cur]=i;    for (int i=1;i<=n;i++)    {        for (int j=1;j<=d;j++)            fa[j][i]=i,s[j][i]=1,hash[i]+=power[j]*i;        insert(hash[i]);    }    for (int i=1;i<=m;i++)    {        int u=read(),v=read(),w=read();        unite(w,u,v);        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击