hdu5923 Prediction

来源:互联网 发布:制作菜单的软件 编辑:程序博客网 时间:2024/05/16 18:42

jxt的思路 先膜一发
先处理 T这棵树上每个点到祖先这条链的点所生成的并查集
每个点的并查集都得分开来存
这个dfs做就好了
最后询问的时候 将k 个点的并查集合并就是这个询问的连通图
易得答案

#include<bits/stdc++.h>using namespace std;#define sz(X)  ((int)X.size())int n,m,q;vector<int> mp[10005];int f[10005][505];int find(int x, int ty){return x==f[ty][x]?x:(f[ty][x]=find(f[ty][x], ty));}int E[10005][2];int so[505];int cn[505];void dfs(int x, int pre) {    for(int i = 1; i <= n; ++i) f[x][i] = f[pre][i];    int fx= find(E[x][0],x); int fy = find(E[x][1],x);    if(fx != fy) f[x][fx] = fy;    for(int i = 0; i < sz(mp[x]); ++i) {        int y = mp[x][i];        dfs(y,x);    }}int main(){    int _; scanf("%d",&_);    for(int cas=1;cas<=_;cas++) {        memset(cn,0,sizeof(cn));        scanf("%d %d",&n,&m);        for(int i = 1; i <= n; ++i) f[1][i] = i;        for(int i = 1; i <= m; ++i) mp[i].clear();        for(int i = 2; i <= m; ++i) {            int a; scanf("%d",&a);            mp[a].push_back(i);        }        for(int i = 1; i <= m; ++i) {            scanf("%d %d",&E[i][0],&E[i][1]);        }        dfs(1,1);        scanf("%d",&q);        printf("Case #%d:\n",cas);        for(int i = 1; i <= q; ++i) {            for(int j = 1; j <= n; ++j) f[0][j] = j;            int k; scanf("%d",&k);            for(int j = 0; j < k; ++j) {                int a; scanf("%d",&a);                for(int l = 1; l <= n; l++) {                    int t1 = find(l,a);                    if(t1 != l) {                        int x = find(t1,0); int y = find(l,0);                        if(x != y) f[0][x] = y;                    }                }            }            int ans = 0;            for(int j = 1; j <= n; ++j) {                int x = find(j,0);                if(cn[x] < i) ans ++;                cn[x] = i;            }            printf("%d\n",ans);        }    }    return 0;}
0 0
原创粉丝点击