【ONTAK2015】【BZOJ4298】Bajtocja

来源:互联网 发布:淘桃美工网 编辑:程序博客网 时间:2024/06/06 15:38

Description

给定d张无向图,每张图都有n个点。一开始,在任何一张图中都没有任何边。接下来有m次操作,每次操作会给出a,b,k,意为在第k张图中的点a和点b之间添加一条无向边。你需要在每次操作之后输出有序数对(a,b)的个数,使得1<=a,b<=n,且a点和b点在d张图中都连通。
Input

第一行包含三个正整数d,n,m(1<=d<=200,1<=n<=5000,1<=m<=1000000),依次表示图的个数,点的个数和操作的个数。
接下来m行,每行包含三个正整数a,b,k(1<=a,b<=n,1<=k<=d),依次描述每一个操作。
Output

输出m行m个正整数,依次表示每次操作之后满足条件的有序数对(a,b)的个数。
Sample Input

3 4 10

1 2 1

2 1 2

1 2 3

3 4 1

1 3 2

2 3 3

2 4 2

3 4 3

3 4 2

1 3 1
Sample Output

4

4

6

6

6

6

6

8

8

16

HINT

Source

By Claris

这里写图片描述

友情提示:这题卡unsigned int 的自然溢出,不卡unsigned long long的自然溢出

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 5010#define T 210#define U unsigned long long#define P 793999#define GET (ch>='0'&&ch<='9')#define base 60383using namespace std;int d,n,m,top;U Pow[T],hash[MAXN];int ans;void in(int &x){    char ch=getchar();x=0;    while (!GET)    ch=getchar();    while (GET) x=x*10+ch-'0',ch=getchar();}struct edge{    int to;    U w;    edge *next;}e[T*MAXN<<1],*prev[T][MAXN];void insert(int d,int u,int v)  {   e[++top].to=v;e[top].next=prev[d][u];prev[d][u]=&e[top];    }int f[T][MAXN],size[T][MAXN];void dfs(int d,int x,int last,int fa);void Union(int d,int x,int y){    if (f[d][x]==f[d][y])   return;    if (size[d][f[d][x]]>size[d][f[d][y]])  swap(x,y);    size[d][f[d][y]]+=size[d][f[d][x]];    insert(d,x,y);insert(d,y,x);    dfs(d,x,y,f[d][y]);}int Top;struct Hash_Table{    U w;    int cnt;    Hash_Table *next;}E[MAXN],*Prev[P+10],*sta[MAXN];void ins(U v){    U t=v%P;Hash_Table *i=Prev[t];    for (;i;i=i->next)  if (i->w==v)    {   ans+=(i->cnt<<1)+1;i->cnt++;return; }    ans++;Hash_Table* j=sta[Top--];    j->w=v;j->cnt=1;j->next=Prev[t];Prev[t]=j;}void del(U v){    U t=v%P;Hash_Table *i=Prev[t],*j=i;    if (i->w==v)    {        ans-=(i->cnt<<1)-1;        if (!(--i->cnt))    sta[++Top]=i,Prev[t]=sta[Top]->next;        return;    }    for (i=i->next;i;j=i,i=i->next)        if (i->w==v)        {            ans-=(i->cnt<<1)-1;            if (!(--i->cnt))    sta[++Top]=i,j->next=i->next;            return;        }}void dfs(int d,int x,int last,int fa){    del(hash[x]);    hash[x]-=Pow[d]*f[d][x];f[d][x]=fa;    hash[x]+=Pow[d]*f[d][x];ins(hash[x]);    for (edge *i=prev[d][x];i;i=i->next)    if (i->to!=last)    dfs(d,i->to,x,fa);}int main(){    in(d);in(n);in(m);Pow[0]=1;int u,v,w;    for (int i=1;i<=d;i++)  Pow[i]=Pow[i-1]*base;    for (int i=1;i<=n;i++)  sta[++Top]=&E[i];    for (int i=1;i<=n;ins(hash[i++]))        for (int j=1;j<=d;j++)  f[j][i]=i,size[j][i]=1,hash[i]+=Pow[j]*i;    while (m--)    {        in(u);in(v);in(w);Union(w,u,v);        printf("%d\n",ans);    }}
1 0
原创粉丝点击