HDU-5923 Prediction(并查集/暴力)

来源:互联网 发布:c语言中lf是什么意思 编辑:程序博客网 时间:2024/04/28 06:03

传送门:HDU-5923

题意:给你一个图G(V,E),n个点m条边。然后有一棵点数为m的树T,根为1, 树中每个点对应为图G的每条边 

接下来有q次查询,每次查询有一个点数为k的集合S, 如果一个树中一个点在集合S中,那么它的祖先也都要加入集合S,问由集合S组成的图G‘有多少个连通块

吐槽:表示从来没用过如此暴力的并查集,30w*500的复杂度竟然可以随便过(还有T组数据。。。

题解:并查集+暴力

首先对于树从根节点DFS一次,每个节点都建一个并查集,每次都将自己的边edge[u]与父节点的并查集f[pre[u]]合并得到自己的并查集f[u],查询的时候合并k个点的并查集即可(简单暴力,可持久化什么的不存在的)

#include<cstdio>#include<string.h>#include<algorithm>#define x first#define y second#define FIN freopen("in.txt","r",stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int MX = 505;const int MXM = 10005;struct Edge {    int v, nxt;} E[MXM];PII edge[MXM];int f[MXM][MX];int pre[MXM], head[MXM], tot, n, m;void add(int u, int v) {    E[tot].v = v;    E[tot].nxt = head[u];    head[u] = tot++;}void init() {    for (int i = 1; i <= n; i++) f[0][i] = i;    for (int i = 1; i <= m; i++) head[i] = -1;    tot = 0;}int find(int i, int x) {    return f[i][x] == x ? x : (f[i][x] = find(i, f[i][x]));}int mcpy(int pre, int u) {    for (int i = 1; i <= n; i++) f[u][i] = f[pre][i];}void dfs(int u) {    mcpy(pre[u], u);    int p1 = find(u, edge[u].x), p2 = find(u, edge[u].y);    if (p1 != p2) f[u][p1] = p2;    for (int i = head[u]; ~i; i = E[i].nxt) dfs(E[i].v);}int main() {    //FIN;    int T, q, cas = 0;    scanf("%d", &T);    while (T--) {        scanf("%d%d", &n, &m);        init();        for (int i = 2; i <= m; i++) {            scanf("%d", &pre[i]);            add(pre[i], i);        }        for (int i = 1; i <= m; i++)            scanf("%d%d", &edge[i].x, &edge[i].y);        dfs(1);        printf("Case #%d:\n", ++cas);        scanf("%d", &q);        while (q--) {            int num, u;            scanf("%d", &num);            mcpy(0, m + 1);            for (int i = 1; i <= num; i++) {                scanf("%d", &u);                for (int j = 1; j <= n; j++) {                    int p1 = find(m + 1, j), p2 = find(u, j);                    int p3 = find(m + 1, p2);                    if (p1 != p3) f[m + 1][p1] = p3;                }            }            int ans = 0;            for (int i = 1; i <= n; i++) if (find(m + 1, i) == i) ans++;            printf("%d\n", ans);        }    }    return 0;}




原创粉丝点击