HDU 5923 Prediction (并查集)

来源:互联网 发布:java开发app 编辑:程序博客网 时间:2024/03/29 00:51

题意: 给定一个图G={VG,EG},同时给定一个树T={VTEG,ET},给定q组树上的点集合Vi,问由Vi以及Vi所有节点的父节点节点说构成的子图G={VG,EGVi or EG is ancent of Vi},问G中有几个联通块

思路:好题,使用了并查集的联通块判断数,同时还使用了类似可持续化的思想,保存树上任意节点VT从根节点到该节点的并查集状态,然后对于每次询问,合并不同状态的并查集即可。时间复杂度O(q|EG||VG|)

#include <iostream>#include <stack>#include <queue>#include <vector>#include <map>#include <string>#include <string.h>#include <cstring>#include <cstdlib>#include <set>#include <algorithm>#include <cctype>#include<cmath>#include <sstream>#include<cstdio>#include <bitset>using namespace std;#define sp system("pause");typedef long long ll;typedef pair<int, int> pii;typedef pair<string, int> psi;#define eps 1e-9 #define PI acos(-1.0)//typedef long long LL;//typedef __int64 LL;const int MAXN = 600;const int MAXM = 30000;vector<int>t[MAXM];int g[MAXM][2];int fa[MAXM][MAXN];int ans[MAXN];int getfa(int d, int x){    return fa[d][x] == x ? x : fa[d][x] = getfa(d, fa[d][x]);}void merge(int d, int a, int b){    int faa = getfa(d, a);    int fbb = getfa(d, b);    if (faa != fbb)    {        if (faa > fbb)swap(faa, fbb);        fa[d][fbb] = fa[d][faa];    }}int n, m;void dfs(int f, int u){    for (int i = 1; i <= n; i++)fa[u][i] = fa[f][i];    merge(u, g[u-1][0], g[u-1][1]);    for (int i = 0; i < t[u].size(); i++)    if (t[u][i] != f) dfs(u, t[u][i]);}int main(){    int T;    cin >> T;    int cas = 1;    while (T--)    {        printf("Case #%d:\n", cas++);        scanf("%d%d", &n, &m);        for (int i = 0; i <=m; i++)t[i].clear();        for (int i = 1; i < m; i++)        {            int u;            scanf("%d", &u);            t[u].push_back(i + 1);        }        for (int i = 0; i < m; i++)            scanf("%d%d", &g[i][0], &g[i][1]);        for (int i = 0; i <= n; i++)fa[0][i] = i;        dfs(0, 1);        int q;        scanf("%d", &q);        while (q--)        {            for (int i = 0; i <= n; i++)fa[m + 1][i] = i;            int tn;            scanf("%d", &tn);            for (int i = 0; i < tn; i++)            {                int x;                scanf("%d", &x);                for (int j = 1; j <= n; j++)                    merge(m + 1, j, getfa(x, j));            }            int aans = 0;            for (int i = 1; i <= n; i++)if (fa[m + 1][i] == i)aans++;            printf("%d\n", aans);        }    }}
0 0
原创粉丝点击