[HDU 5923]Prediction:并查集

来源:互联网 发布:传奇霸业神威宝石数据 编辑:程序博客网 时间:2024/04/28 05:27

点击这里查看原题

考虑到n很小,对于树上每个点,选择它便会同时选择它的所有祖先,因此可以对每个点维护一个并查集,询问时做并查集合并即可。
复杂度O(nm+nk)。
不知道为何,我的get函数不加inline就会TLE,加上立马就过了,因为这个问题调了好几个小时。

/*User:SmallLanguage:C++Problem No.:5923*/#include<bits/stdc++.h>#define ll long long#define inf 999999999using namespace std;const int M=1e4+5;int f[M][505],d[505],n,m,q;vector<int> g[M];struct no{    int u,v;}p[M];inline int get(int *f,int x){    return x==f[x]?x:f[x]=get(f,f[x]);}inline void join(int *f,int x,int y){    x=get(f,x),y=get(f,y);    f[y]=x;}void dfs(int u,int fa){    for(int i=1;i<=n;i++) f[u][i]=f[fa][i];    join(f[u],p[u].u,p[u].v);    vector<int>::iterator it;    for(it=g[u].begin();it!=g[u].end();it++)        dfs(*it,u);}inline void solve(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++) g[i].clear();    for(int i=2;i<=m;i++){        int x;        scanf("%d",&x);        g[x].push_back(i);    }    for(int i=1;i<=m;i++)        scanf("%d%d",&p[i].u,&p[i].v);    for(int i=1;i<=n;i++) f[0][i]=i;    dfs(1,0);    scanf("%d",&q);    while(q--){        int k,x,res=0;        scanf("%d",&k);        for(int i=1;i<=n;i++) d[i]=f[0][i];        while(k--){            scanf("%d",&x);            for(int i=1;i<=n;i++)                join(d,i,get(f[x],i));        }        for(int i=1;i<=n;i++) if(d[i]==i) res++;        printf("%d\n",res);    }}   int main(){    freopen("data.in","r",stdin);//    int t;    scanf("%d",&t);    for(int i=1;i<=t;i++){        printf("Case #%d:\n",i);        solve();    }    return 0;}
0 0
原创粉丝点击